mirror of https://github.com/vector-im/riot-web
Add option to change the size of images/videos in the timeline (#7017)
Co-authored-by: Šimon Brandner <simon.bra.ag@gmail.com> Co-authored-by: J. Ryan Stinnett <jryans@gmail.com> Co-authored-by: Timo K <toger5@hotmail.de>pull/21833/head
parent
816136de97
commit
3c06e7f7a0
|
@ -32,6 +32,7 @@ $slider-selection-dot-size: 2.4em;
|
||||||
|
|
||||||
$container-border-width: 8px;
|
$container-border-width: 8px;
|
||||||
|
|
||||||
|
$timeline-image-boarder-radius: 8px;
|
||||||
:root {
|
:root {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
|
|
||||||
|
|
|
@ -252,6 +252,7 @@
|
||||||
@import "./views/settings/_E2eAdvancedPanel.scss";
|
@import "./views/settings/_E2eAdvancedPanel.scss";
|
||||||
@import "./views/settings/_EmailAddresses.scss";
|
@import "./views/settings/_EmailAddresses.scss";
|
||||||
@import "./views/settings/_FontScalingPanel.scss";
|
@import "./views/settings/_FontScalingPanel.scss";
|
||||||
|
@import "./views/settings/_ImageSizePanel.scss";
|
||||||
@import "./views/settings/_IntegrationManager.scss";
|
@import "./views/settings/_IntegrationManager.scss";
|
||||||
@import "./views/settings/_JoinRuleSettings.scss";
|
@import "./views/settings/_JoinRuleSettings.scss";
|
||||||
@import "./views/settings/_LayoutSwitcher.scss";
|
@import "./views/settings/_LayoutSwitcher.scss";
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
Copyright 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.
|
||||||
|
@ -14,7 +15,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$timelineImageBorderRadius: 4px;
|
$timeline-image-boarder-radius: 8px;
|
||||||
|
|
||||||
.mx_MImageBody_thumbnail--blurhash {
|
.mx_MImageBody_thumbnail--blurhash {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -24,7 +25,7 @@ $timelineImageBorderRadius: 4px;
|
||||||
|
|
||||||
.mx_MImageBody_thumbnail {
|
.mx_MImageBody_thumbnail {
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
border-radius: $timelineImageBorderRadius;
|
border-radius: $timeline-image-boarder-radius;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -32,9 +33,10 @@ $timelineImageBorderRadius: 4px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
// this is needed so that the Blurhash can get have rounded corners without beeing the correct size during loading.
|
||||||
|
overflow: hidden;
|
||||||
.mx_Blurhash > canvas {
|
.mx_Blurhash > canvas {
|
||||||
animation: mx--anim-pulse 1.75s infinite cubic-bezier(.4, 0, .6, 1);
|
animation: mx--anim-pulse 1.75s infinite cubic-bezier(.4, 0, .6, 1);
|
||||||
border-radius: $timelineImageBorderRadius;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_no-image-placeholder {
|
.mx_no-image-placeholder {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
Copyright 2020 - 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,6 @@ span.mx_MVideoBody {
|
||||||
video.mx_MVideoBody {
|
video.mx_MVideoBody {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
border-radius: 4px;
|
border-radius: $timeline-image-boarder-radius;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.mx_ImageSizePanel {
|
||||||
|
color: $primary-content;
|
||||||
|
|
||||||
|
.mx_ImageSizePanel_radios {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 16px; // move away from header a bit
|
||||||
|
|
||||||
|
> label {
|
||||||
|
margin-right: 68px; // keep the boxes separate
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_ImageSizePanel_size {
|
||||||
|
background-color: $quinary-content;
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-size: 221px;
|
||||||
|
mask-position: center;
|
||||||
|
width: 221px;
|
||||||
|
height: 148px;
|
||||||
|
margin-bottom: 14px; // move radio button away from bottom edge a bit
|
||||||
|
|
||||||
|
&.mx_ImageSizePanel_sizeDefault {
|
||||||
|
mask: url("$(res)/img/element-icons/settings/img-size-normal.svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mx_ImageSizePanel_sizeLarge {
|
||||||
|
mask: url("$(res)/img/element-icons/settings/img-size-large.svg");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
<svg width="221" height="148" viewBox="0 0 221 148" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
<mask id="mountains">
|
||||||
|
<rect x="0" y="0" width="100%" height="100%" fill="white" />
|
||||||
|
<path d="M109.918 67.966L80.2282 114.975C79.0024 116.916 80.3971 119.447 82.6927 119.447H142.073C144.369 119.447 145.763 116.916 144.538 114.975L114.847 67.966C113.704 66.1548 111.062 66.1548 109.918 67.966Z" fill="black"/>
|
||||||
|
<path d="M141.995 82.4526L121.1 114.956C119.853 116.896 121.246 119.447 123.552 119.447H165.342C167.648 119.447 169.041 116.896 167.794 114.956L146.899 82.4526C145.751 80.6677 143.142 80.6677 141.995 82.4526Z" fill="black"/>
|
||||||
|
<circle cx="161.936" cy="61.1488" r="11.6596" fill="black"/>
|
||||||
|
</mask>
|
||||||
|
</defs>
|
||||||
|
<rect x="0.5" y="0.5" width="220" height="147" rx="7.5" stroke="#E3E8F0"/>
|
||||||
|
<rect x="57" y="14" width="10" height="10" rx="1.5" fill="#E3E8F0"/>
|
||||||
|
<rect x="70" y="14" width="60" height="10" rx="1.5" fill="#E3E8F0"/>
|
||||||
|
<path d="M0 8C0 3.58173 3.58172 0 8 0H45C45.5523 0 46 0.447715 46 1V147C46 147.552 45.5523 148 45 148H8C3.58172 148 0 144.418 0 140V8Z" fill="#E3E8F0"/>
|
||||||
|
<rect x="57" y="32" width="137" height="102.021" rx="5.82979" fill="#E3E8F0" mask="url(#mountains)"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1,20 @@
|
||||||
|
<svg width="221" height="148" viewBox="0 0 221 148" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
<mask id="mountains">
|
||||||
|
<rect x="0" y="0" width="100%" height="100%" fill="white" />
|
||||||
|
<path d="M75.1545 94.3387L64.9688 110.466C64.5483 111.132 65.0268 112 65.8143 112H86.1857C86.9732 112 87.4517 111.132 87.0312 110.466L76.8455 94.3387C76.4531 93.7173 75.5469 93.7173 75.1545 94.3387Z" fill="black"/>
|
||||||
|
<path d="M86.1588 99.3085L78.9905 110.459C78.5627 111.125 79.0405 112 79.8317 112H94.1683C94.9595 112 95.4373 111.125 95.0095 110.459L87.8412 99.3085C87.4475 98.6962 86.5525 98.6962 86.1588 99.3085Z" fill="black"/>
|
||||||
|
<circle cx="93" cy="92" r="4" fill="black"/>
|
||||||
|
</mask>
|
||||||
|
</defs>
|
||||||
|
<rect x="0.5" y="0.5" width="220" height="147" rx="7.5" stroke="#E3E8F0"/>
|
||||||
|
<rect x="57" y="14" width="10" height="10" rx="1.5" fill="#E3E8F0"/>
|
||||||
|
<rect x="57" y="64" width="10" height="10" rx="1.5" fill="#E3E8F0"/>
|
||||||
|
<rect x="57" y="125" width="10" height="10" rx="1.5" fill="#E3E8F0"/>
|
||||||
|
<rect x="70" y="14" width="60" height="10" rx="1.5" fill="#E3E8F0"/>
|
||||||
|
<rect x="70" y="64" width="60" height="10" rx="1.5" fill="#E3E8F0"/>
|
||||||
|
<rect x="70" y="125" width="60" height="10" rx="1.5" fill="#E3E8F0"/>
|
||||||
|
<path d="M57 32.5C57 31.6716 57.6716 31 58.5 31H208.5C209.328 31 210 31.6716 210 32.5V54.5C210 55.3284 209.328 56 208.5 56H58.5C57.6716 56 57 55.3284 57 54.5V32.5Z" fill="#E3E8F0"/>
|
||||||
|
<path d="M0 8C0 3.58173 3.58172 0 8 0H45C45.5523 0 46 0.447715 46 1V147C46 147.552 45.5523 148 45 148H8C3.58172 148 0 144.418 0 140V8Z" fill="#E3E8F0"/>
|
||||||
|
<rect x="57" y="82" width="47" height="35" rx="2" fill="#E3E8F0" mask="url(#mountains)" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
|
@ -36,7 +36,7 @@ import ResizeNotifier from '../../utils/ResizeNotifier';
|
||||||
import TimelinePanel from "./TimelinePanel";
|
import TimelinePanel from "./TimelinePanel";
|
||||||
import Spinner from "../views/elements/Spinner";
|
import Spinner from "../views/elements/Spinner";
|
||||||
import { TileShape } from '../views/rooms/EventTile';
|
import { TileShape } from '../views/rooms/EventTile';
|
||||||
import { Layout } from "../../settings/Layout";
|
import { Layout } from "../../settings/enums/Layout";
|
||||||
import RoomContext, { TimelineRenderingType } from '../../contexts/RoomContext';
|
import RoomContext, { TimelineRenderingType } from '../../contexts/RoomContext';
|
||||||
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { wantsDateSeparator } from '../../DateUtils';
|
||||||
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
import { MatrixClientPeg } from '../../MatrixClientPeg';
|
||||||
import SettingsStore from '../../settings/SettingsStore';
|
import SettingsStore from '../../settings/SettingsStore';
|
||||||
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
|
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
|
||||||
import { Layout } from "../../settings/Layout";
|
import { Layout } from "../../settings/enums/Layout";
|
||||||
import { _t } from "../../languageHandler";
|
import { _t } from "../../languageHandler";
|
||||||
import EventTile, { haveTileForEvent, IReadReceiptProps, TileShape } from "../views/rooms/EventTile";
|
import EventTile, { haveTileForEvent, IReadReceiptProps, TileShape } from "../views/rooms/EventTile";
|
||||||
import { hasText } from "../../TextForEvent";
|
import { hasText } from "../../TextForEvent";
|
||||||
|
|
|
@ -23,7 +23,7 @@ import { replaceableComponent } from "../../utils/replaceableComponent";
|
||||||
import TimelinePanel from "./TimelinePanel";
|
import TimelinePanel from "./TimelinePanel";
|
||||||
import Spinner from "../views/elements/Spinner";
|
import Spinner from "../views/elements/Spinner";
|
||||||
import { TileShape } from "../views/rooms/EventTile";
|
import { TileShape } from "../views/rooms/EventTile";
|
||||||
import { Layout } from "../../settings/Layout";
|
import { Layout } from "../../settings/enums/Layout";
|
||||||
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
|
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
|
||||||
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
|
@ -44,7 +44,7 @@ import RoomViewStore from '../../stores/RoomViewStore';
|
||||||
import RoomScrollStateStore, { ScrollState } from '../../stores/RoomScrollStateStore';
|
import RoomScrollStateStore, { ScrollState } from '../../stores/RoomScrollStateStore';
|
||||||
import WidgetEchoStore from '../../stores/WidgetEchoStore';
|
import WidgetEchoStore from '../../stores/WidgetEchoStore';
|
||||||
import SettingsStore from "../../settings/SettingsStore";
|
import SettingsStore from "../../settings/SettingsStore";
|
||||||
import { Layout } from "../../settings/Layout";
|
import { Layout } from "../../settings/enums/Layout";
|
||||||
import AccessibleButton from "../views/elements/AccessibleButton";
|
import AccessibleButton from "../views/elements/AccessibleButton";
|
||||||
import RightPanelStore from "../../stores/RightPanelStore";
|
import RightPanelStore from "../../stores/RightPanelStore";
|
||||||
import { haveTileForEvent } from "../views/rooms/EventTile";
|
import { haveTileForEvent } from "../views/rooms/EventTile";
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { ContextMenuButton } from '../../accessibility/context_menu/ContextMenuB
|
||||||
import ContextMenu, { ChevronFace, useContextMenu } from './ContextMenu';
|
import ContextMenu, { ChevronFace, useContextMenu } from './ContextMenu';
|
||||||
import RoomContext, { TimelineRenderingType } from '../../contexts/RoomContext';
|
import RoomContext, { TimelineRenderingType } from '../../contexts/RoomContext';
|
||||||
import TimelinePanel from './TimelinePanel';
|
import TimelinePanel from './TimelinePanel';
|
||||||
import { Layout } from '../../settings/Layout';
|
import { Layout } from '../../settings/enums/Layout';
|
||||||
import { useEventEmitter } from '../../hooks/useEventEmitter';
|
import { useEventEmitter } from '../../hooks/useEventEmitter';
|
||||||
import AccessibleButton from '../views/elements/AccessibleButton';
|
import AccessibleButton from '../views/elements/AccessibleButton';
|
||||||
import { TileShape } from '../views/rooms/EventTile';
|
import { TileShape } from '../views/rooms/EventTile';
|
||||||
|
|
|
@ -27,7 +27,7 @@ import ResizeNotifier from '../../utils/ResizeNotifier';
|
||||||
import { TileShape } from '../views/rooms/EventTile';
|
import { TileShape } from '../views/rooms/EventTile';
|
||||||
import MessageComposer from '../views/rooms/MessageComposer';
|
import MessageComposer from '../views/rooms/MessageComposer';
|
||||||
import { RoomPermalinkCreator } from '../../utils/permalinks/Permalinks';
|
import { RoomPermalinkCreator } from '../../utils/permalinks/Permalinks';
|
||||||
import { Layout } from '../../settings/Layout';
|
import { Layout } from '../../settings/enums/Layout';
|
||||||
import TimelinePanel from './TimelinePanel';
|
import TimelinePanel from './TimelinePanel';
|
||||||
import dis from "../../dispatcher/dispatcher";
|
import dis from "../../dispatcher/dispatcher";
|
||||||
import { ActionPayload } from '../../dispatcher/payloads';
|
import { ActionPayload } from '../../dispatcher/payloads';
|
||||||
|
|
|
@ -25,7 +25,7 @@ import { EventType, RelationType } from 'matrix-js-sdk/src/@types/event';
|
||||||
import { SyncState } from 'matrix-js-sdk/src/sync.api';
|
import { SyncState } from 'matrix-js-sdk/src/sync.api';
|
||||||
|
|
||||||
import SettingsStore from "../../settings/SettingsStore";
|
import SettingsStore from "../../settings/SettingsStore";
|
||||||
import { Layout } from "../../settings/Layout";
|
import { Layout } from "../../settings/enums/Layout";
|
||||||
import { _t } from '../../languageHandler';
|
import { _t } from '../../languageHandler';
|
||||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||||
import RoomContext from "../../contexts/RoomContext";
|
import RoomContext from "../../contexts/RoomContext";
|
||||||
|
|
|
@ -25,7 +25,7 @@ import { _t } from "../../../languageHandler";
|
||||||
import dis from "../../../dispatcher/dispatcher";
|
import dis from "../../../dispatcher/dispatcher";
|
||||||
import { useSettingValue, useFeatureEnabled } from "../../../hooks/useSettings";
|
import { useSettingValue, useFeatureEnabled } from "../../../hooks/useSettings";
|
||||||
import { UIFeature } from "../../../settings/UIFeature";
|
import { UIFeature } from "../../../settings/UIFeature";
|
||||||
import { Layout } from "../../../settings/Layout";
|
import { Layout } from "../../../settings/enums/Layout";
|
||||||
import { IDialogProps } from "./IDialogProps";
|
import { IDialogProps } from "./IDialogProps";
|
||||||
import BaseDialog from "./BaseDialog";
|
import BaseDialog from "./BaseDialog";
|
||||||
import { avatarUrlForUser } from "../../../Avatar";
|
import { avatarUrlForUser } from "../../../Avatar";
|
||||||
|
|
|
@ -22,7 +22,7 @@ import MemberAvatar from '../avatars/MemberAvatar';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import { useStateToggle } from "../../../hooks/useStateToggle";
|
import { useStateToggle } from "../../../hooks/useStateToggle";
|
||||||
import AccessibleButton from "./AccessibleButton";
|
import AccessibleButton from "./AccessibleButton";
|
||||||
import { Layout } from '../../../settings/Layout';
|
import { Layout } from '../../../settings/enums/Layout';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
// An array of member events to summarise
|
// An array of member events to summarise
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
|
||||||
import * as Avatar from '../../../Avatar';
|
import * as Avatar from '../../../Avatar';
|
||||||
import EventTile from '../rooms/EventTile';
|
import EventTile from '../rooms/EventTile';
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import { Layout } from "../../../settings/Layout";
|
import { Layout } from "../../../settings/enums/Layout";
|
||||||
import { UIFeature } from "../../../settings/UIFeature";
|
import { UIFeature } from "../../../settings/UIFeature";
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
import Spinner from './Spinner';
|
import Spinner from './Spinner';
|
||||||
|
|
|
@ -31,7 +31,7 @@ import { Action } from '../../../dispatcher/actions';
|
||||||
import { SetRightPanelPhasePayload } from '../../../dispatcher/payloads/SetRightPanelPhasePayload';
|
import { SetRightPanelPhasePayload } from '../../../dispatcher/payloads/SetRightPanelPhasePayload';
|
||||||
import { jsxJoin } from '../../../utils/ReactUtils';
|
import { jsxJoin } from '../../../utils/ReactUtils';
|
||||||
import { EventType } from 'matrix-js-sdk/src/@types/event';
|
import { EventType } from 'matrix-js-sdk/src/@types/event';
|
||||||
import { Layout } from '../../../settings/Layout';
|
import { Layout } from '../../../settings/enums/Layout';
|
||||||
|
|
||||||
const onPinnedMessagesClick = (): void => {
|
const onPinnedMessagesClick = (): void => {
|
||||||
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
|
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
|
||||||
|
|
|
@ -23,7 +23,7 @@ import dis from '../../../dispatcher/dispatcher';
|
||||||
import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
|
import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
|
||||||
import { makeUserPermalink, RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
import { makeUserPermalink, RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import { Layout } from "../../../settings/Layout";
|
import { Layout } from "../../../settings/enums/Layout";
|
||||||
import escapeHtml from "escape-html";
|
import escapeHtml from "escape-html";
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import { getUserNameColorClass } from "../../../utils/FormattingUtils";
|
import { getUserNameColorClass } from "../../../utils/FormattingUtils";
|
||||||
|
|
|
@ -35,6 +35,7 @@ import classNames from 'classnames';
|
||||||
import { CSSTransition, SwitchTransition } from 'react-transition-group';
|
import { CSSTransition, SwitchTransition } from 'react-transition-group';
|
||||||
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
import { ImageSize, suggestedSize as suggestedImageSize } from "../../../settings/enums/ImageSize";
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
decryptedUrl?: string;
|
decryptedUrl?: string;
|
||||||
|
@ -58,6 +59,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
|
||||||
private unmounted = true;
|
private unmounted = true;
|
||||||
private image = createRef<HTMLImageElement>();
|
private image = createRef<HTMLImageElement>();
|
||||||
private timeout?: number;
|
private timeout?: number;
|
||||||
|
private sizeWatcher: string;
|
||||||
|
|
||||||
constructor(props: IBodyProps) {
|
constructor(props: IBodyProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -317,12 +319,17 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
|
||||||
}
|
}
|
||||||
}, 150);
|
}, 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.sizeWatcher = SettingsStore.watchSetting("Images.size", null, () => {
|
||||||
|
this.forceUpdate(); // we don't really have a reliable thing to update, so just update the whole thing
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.unmounted = true;
|
this.unmounted = true;
|
||||||
this.context.removeListener('sync', this.onClientSync);
|
this.context.removeListener('sync', this.onClientSync);
|
||||||
this.clearBlurhashTimeout();
|
this.clearBlurhashTimeout();
|
||||||
|
SettingsStore.unwatchSetting(this.sizeWatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected messageContent(
|
protected messageContent(
|
||||||
|
@ -367,11 +374,25 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
|
||||||
infoHeight = this.state.loadedImageDimensions.naturalHeight;
|
infoHeight = this.state.loadedImageDimensions.naturalHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The maximum height of the thumbnail as it is rendered as an <img>
|
// The maximum size of the thumbnail as it is rendered as an <img>
|
||||||
const maxHeight = forcedHeight || Math.min((this.props.maxImageHeight || 600), infoHeight);
|
// check for any height constraints
|
||||||
// The maximum width of the thumbnail, as dictated by its natural
|
const imageSize = SettingsStore.getValue("Images.size") as ImageSize;
|
||||||
// maximum height.
|
const suggestedAndPossibleWidth = Math.min(suggestedImageSize(imageSize).w, infoWidth);
|
||||||
const maxWidth = infoWidth * maxHeight / infoHeight;
|
const aspectRatio = infoWidth / infoHeight;
|
||||||
|
|
||||||
|
let maxWidth;
|
||||||
|
let maxHeight;
|
||||||
|
const maxHeightConstraint = forcedHeight || this.props.maxImageHeight || undefined;
|
||||||
|
if (maxHeightConstraint && maxHeightConstraint * aspectRatio < suggestedAndPossibleWidth) {
|
||||||
|
// width is dictated by the maximum height that was defined by the props or the function param `forcedHeight`
|
||||||
|
maxWidth = maxHeightConstraint * aspectRatio;
|
||||||
|
// there is no need to check for infoHeight here since this is done with `maxHeightConstraint * aspectRatio < suggestedAndPossibleWidth`
|
||||||
|
maxHeight = maxHeightConstraint;
|
||||||
|
} else {
|
||||||
|
// height is dictated by suggestedWidth (based on the Image.size setting)
|
||||||
|
maxWidth = suggestedAndPossibleWidth;
|
||||||
|
maxHeight = suggestedAndPossibleWidth / aspectRatio;
|
||||||
|
}
|
||||||
|
|
||||||
let img = null;
|
let img = null;
|
||||||
let placeholder = null;
|
let placeholder = null;
|
||||||
|
|
|
@ -28,6 +28,7 @@ import { IBodyProps } from "./IBodyProps";
|
||||||
import MFileBody from "./MFileBody";
|
import MFileBody from "./MFileBody";
|
||||||
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
import { ImageSize, suggestedSize as suggestedVideoSize } from "../../../settings/enums/ImageSize";
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
decryptedUrl?: string;
|
decryptedUrl?: string;
|
||||||
|
@ -42,6 +43,7 @@ interface IState {
|
||||||
@replaceableComponent("views.messages.MVideoBody")
|
@replaceableComponent("views.messages.MVideoBody")
|
||||||
export default class MVideoBody extends React.PureComponent<IBodyProps, IState> {
|
export default class MVideoBody extends React.PureComponent<IBodyProps, IState> {
|
||||||
private videoRef = React.createRef<HTMLVideoElement>();
|
private videoRef = React.createRef<HTMLVideoElement>();
|
||||||
|
private sizeWatcher: string;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -57,7 +59,22 @@ export default class MVideoBody extends React.PureComponent<IBodyProps, IState>
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
thumbScale(fullWidth: number, fullHeight: number, thumbWidth = 480, thumbHeight = 360) {
|
private get suggestedDimensions(): { w: number, h: number } {
|
||||||
|
return suggestedVideoSize(SettingsStore.getValue("Images.size") as ImageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private thumbScale(
|
||||||
|
fullWidth: number,
|
||||||
|
fullHeight: number,
|
||||||
|
thumbWidth?: number,
|
||||||
|
thumbHeight?: number,
|
||||||
|
): number {
|
||||||
|
if (!thumbWidth || !thumbHeight) {
|
||||||
|
const dims = this.suggestedDimensions;
|
||||||
|
thumbWidth = dims.w;
|
||||||
|
thumbHeight = dims.h;
|
||||||
|
}
|
||||||
|
|
||||||
if (!fullWidth || !fullHeight) {
|
if (!fullWidth || !fullHeight) {
|
||||||
// Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even
|
// Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even
|
||||||
// log this because it's spammy
|
// log this because it's spammy
|
||||||
|
@ -68,14 +85,8 @@ export default class MVideoBody extends React.PureComponent<IBodyProps, IState>
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
const widthMulti = thumbWidth / fullWidth;
|
const widthMulti = thumbWidth / fullWidth;
|
||||||
const heightMulti = thumbHeight / fullHeight;
|
// always scale the videos based on their width.
|
||||||
if (widthMulti < heightMulti) {
|
return widthMulti;
|
||||||
// width is the dominant dimension so scaling will be fixed on that
|
|
||||||
return widthMulti;
|
|
||||||
} else {
|
|
||||||
// height is the dominant dimension so scaling will be fixed on that
|
|
||||||
return heightMulti;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getContentUrl(): string|null {
|
private getContentUrl(): string|null {
|
||||||
|
@ -152,12 +163,16 @@ export default class MVideoBody extends React.PureComponent<IBodyProps, IState>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
public async componentDidMount() {
|
||||||
const autoplay = SettingsStore.getValue("autoplayVideo") as boolean;
|
this.sizeWatcher = SettingsStore.watchSetting("Images.size", null, () => {
|
||||||
|
this.forceUpdate(); // we don't really have a reliable thing to update, so just update the whole thing
|
||||||
|
});
|
||||||
|
|
||||||
this.loadBlurhash();
|
this.loadBlurhash();
|
||||||
|
|
||||||
if (this.props.mediaEventHelper.media.isEncrypted && this.state.decryptedUrl === null) {
|
if (this.props.mediaEventHelper.media.isEncrypted && this.state.decryptedUrl === null) {
|
||||||
try {
|
try {
|
||||||
|
const autoplay = SettingsStore.getValue("autoplayVideo") as boolean;
|
||||||
const thumbnailUrl = await this.props.mediaEventHelper.thumbnailUrl.value;
|
const thumbnailUrl = await this.props.mediaEventHelper.thumbnailUrl.value;
|
||||||
if (autoplay) {
|
if (autoplay) {
|
||||||
logger.log("Preloading video");
|
logger.log("Preloading video");
|
||||||
|
@ -189,6 +204,10 @@ export default class MVideoBody extends React.PureComponent<IBodyProps, IState>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public componentWillUnmount() {
|
||||||
|
SettingsStore.unwatchSetting(this.sizeWatcher);
|
||||||
|
}
|
||||||
|
|
||||||
private videoOnPlay = async () => {
|
private videoOnPlay = async () => {
|
||||||
if (this.hasContentUrl() || this.state.fetchingData || this.state.error) {
|
if (this.hasContentUrl() || this.state.fetchingData || this.state.error) {
|
||||||
// We have the file, we are fetching the file, or there is an error.
|
// We have the file, we are fetching the file, or there is an error.
|
||||||
|
@ -249,8 +268,9 @@ export default class MVideoBody extends React.PureComponent<IBodyProps, IState>
|
||||||
|
|
||||||
const contentUrl = this.getContentUrl();
|
const contentUrl = this.getContentUrl();
|
||||||
const thumbUrl = this.getThumbUrl();
|
const thumbUrl = this.getThumbUrl();
|
||||||
let height = null;
|
const defaultDims = this.suggestedDimensions;
|
||||||
let width = null;
|
let height = defaultDims.h;
|
||||||
|
let width = defaultDims.w;
|
||||||
let poster = null;
|
let poster = null;
|
||||||
let preload = "metadata";
|
let preload = "metadata";
|
||||||
if (content.info) {
|
if (content.info) {
|
||||||
|
|
|
@ -28,7 +28,7 @@ import { _t } from '../../../languageHandler';
|
||||||
import { hasText } from "../../../TextForEvent";
|
import { hasText } from "../../../TextForEvent";
|
||||||
import * as sdk from "../../../index";
|
import * as sdk from "../../../index";
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
import { Layout } from "../../../settings/Layout";
|
import { Layout } from "../../../settings/enums/Layout";
|
||||||
import { formatTime } from "../../../DateUtils";
|
import { formatTime } from "../../../DateUtils";
|
||||||
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||||
import { ALL_RULE_TYPES } from "../../../mjolnir/BanList";
|
import { ALL_RULE_TYPES } from "../../../mjolnir/BanList";
|
||||||
|
|
|
@ -22,7 +22,7 @@ import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import Slider from "../elements/Slider";
|
import Slider from "../elements/Slider";
|
||||||
import { FontWatcher } from "../../../settings/watchers/FontWatcher";
|
import { FontWatcher } from "../../../settings/watchers/FontWatcher";
|
||||||
import { IValidationResult, IFieldState } from '../elements/Validation';
|
import { IValidationResult, IFieldState } from '../elements/Validation';
|
||||||
import { Layout } from "../../../settings/Layout";
|
import { Layout } from "../../../settings/enums/Layout";
|
||||||
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||||
import { SettingLevel } from "../../../settings/SettingLevel";
|
import { SettingLevel } from "../../../settings/SettingLevel";
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
import StyledRadioButton from "../elements/StyledRadioButton";
|
||||||
|
import { _t } from "../../../languageHandler";
|
||||||
|
import { SettingLevel } from "../../../settings/SettingLevel";
|
||||||
|
import { ImageSize } from "../../../settings/enums/ImageSize";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
// none
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
size: ImageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ImageSizePanel extends React.Component<IProps, IState> {
|
||||||
|
constructor(props: IProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
size: SettingsStore.getValue("Images.size"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private onSizeChange = (ev: React.ChangeEvent<HTMLInputElement>): void => {
|
||||||
|
const newSize = ev.target.value as ImageSize;
|
||||||
|
this.setState({ size: newSize });
|
||||||
|
|
||||||
|
// noinspection JSIgnoredPromiseFromCall
|
||||||
|
SettingsStore.setValue("Images.size", null, SettingLevel.ACCOUNT, newSize);
|
||||||
|
};
|
||||||
|
|
||||||
|
public render(): JSX.Element {
|
||||||
|
return (
|
||||||
|
<div className="mx_SettingsTab_section mx_ImageSizePanel">
|
||||||
|
<span className="mx_SettingsTab_subheading">
|
||||||
|
{ _t("Image size in the timeline") }
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div className="mx_ImageSizePanel_radios">
|
||||||
|
<label>
|
||||||
|
<div className="mx_ImageSizePanel_size mx_ImageSizePanel_sizeDefault" />
|
||||||
|
<StyledRadioButton
|
||||||
|
name="image_size"
|
||||||
|
value={ImageSize.Normal}
|
||||||
|
checked={this.state.size === ImageSize.Normal}
|
||||||
|
onChange={this.onSizeChange}
|
||||||
|
>{ _t("Default") }</StyledRadioButton>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<div className="mx_ImageSizePanel_size mx_ImageSizePanel_sizeLarge" />
|
||||||
|
<StyledRadioButton
|
||||||
|
name="image_size"
|
||||||
|
value={ImageSize.Large}
|
||||||
|
checked={this.state.size === ImageSize.Large}
|
||||||
|
onChange={this.onSizeChange}
|
||||||
|
>{ _t("Large") }</StyledRadioButton>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import EventTilePreview from "../elements/EventTilePreview";
|
import EventTilePreview from "../elements/EventTilePreview";
|
||||||
import StyledRadioButton from "../elements/StyledRadioButton";
|
import StyledRadioButton from "../elements/StyledRadioButton";
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import { Layout } from "../../../settings/Layout";
|
import { Layout } from "../../../settings/enums/Layout";
|
||||||
import { SettingLevel } from "../../../settings/SettingLevel";
|
import { SettingLevel } from "../../../settings/SettingLevel";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
|
|
|
@ -25,12 +25,13 @@ import SettingsFlag from '../../../elements/SettingsFlag';
|
||||||
import Field from '../../../elements/Field';
|
import Field from '../../../elements/Field';
|
||||||
import { SettingLevel } from "../../../../../settings/SettingLevel";
|
import { SettingLevel } from "../../../../../settings/SettingLevel";
|
||||||
import { UIFeature } from "../../../../../settings/UIFeature";
|
import { UIFeature } from "../../../../../settings/UIFeature";
|
||||||
import { Layout } from "../../../../../settings/Layout";
|
import { Layout } from "../../../../../settings/enums/Layout";
|
||||||
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
|
||||||
import LayoutSwitcher from "../../LayoutSwitcher";
|
import LayoutSwitcher from "../../LayoutSwitcher";
|
||||||
|
|
||||||
import FontScalingPanel from '../../FontScalingPanel';
|
import FontScalingPanel from '../../FontScalingPanel';
|
||||||
import ThemeChoicePanel from '../../ThemeChoicePanel';
|
import ThemeChoicePanel from '../../ThemeChoicePanel';
|
||||||
|
import ImageSizePanel from "../../ImageSizePanel";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
}
|
}
|
||||||
|
@ -188,6 +189,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
|
||||||
{ layoutSection }
|
{ layoutSection }
|
||||||
<FontScalingPanel />
|
<FontScalingPanel />
|
||||||
{ this.renderAdvancedSection() }
|
{ this.renderAdvancedSection() }
|
||||||
|
<ImageSizePanel />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||||
import { createContext } from "react";
|
import { createContext } from "react";
|
||||||
|
|
||||||
import { IRoomState } from "../components/structures/RoomView";
|
import { IRoomState } from "../components/structures/RoomView";
|
||||||
import { Layout } from "../settings/Layout";
|
import { Layout } from "../settings/enums/Layout";
|
||||||
|
|
||||||
export enum TimelineRenderingType {
|
export enum TimelineRenderingType {
|
||||||
Room = "Room",
|
Room = "Room",
|
||||||
|
|
|
@ -1182,6 +1182,8 @@
|
||||||
"Size must be a number": "Size must be a number",
|
"Size must be a number": "Size must be a number",
|
||||||
"Custom font size can only be between %(min)s pt and %(max)s pt": "Custom font size can only be between %(min)s pt and %(max)s pt",
|
"Custom font size can only be between %(min)s pt and %(max)s pt": "Custom font size can only be between %(min)s pt and %(max)s pt",
|
||||||
"Use between %(min)s pt and %(max)s pt": "Use between %(min)s pt and %(max)s pt",
|
"Use between %(min)s pt and %(max)s pt": "Use between %(min)s pt and %(max)s pt",
|
||||||
|
"Image size in the timeline": "Image size in the timeline",
|
||||||
|
"Large": "Large",
|
||||||
"Connecting to integration manager...": "Connecting to integration manager...",
|
"Connecting to integration manager...": "Connecting to integration manager...",
|
||||||
"Cannot connect to integration manager": "Cannot connect to integration manager",
|
"Cannot connect to integration manager": "Cannot connect to integration manager",
|
||||||
"The integration manager is offline or it cannot reach your homeserver.": "The integration manager is offline or it cannot reach your homeserver.",
|
"The integration manager is offline or it cannot reach your homeserver.": "The integration manager is offline or it cannot reach your homeserver.",
|
||||||
|
|
|
@ -37,11 +37,12 @@ import { isMac } from '../Keyboard';
|
||||||
import UIFeatureController from "./controllers/UIFeatureController";
|
import UIFeatureController from "./controllers/UIFeatureController";
|
||||||
import { UIFeature } from "./UIFeature";
|
import { UIFeature } from "./UIFeature";
|
||||||
import { OrderedMultiController } from "./controllers/OrderedMultiController";
|
import { OrderedMultiController } from "./controllers/OrderedMultiController";
|
||||||
import { Layout } from "./Layout";
|
import { Layout } from "./enums/Layout";
|
||||||
import ReducedMotionController from './controllers/ReducedMotionController';
|
import ReducedMotionController from './controllers/ReducedMotionController';
|
||||||
import IncompatibleController from "./controllers/IncompatibleController";
|
import IncompatibleController from "./controllers/IncompatibleController";
|
||||||
import PseudonymousAnalyticsController from './controllers/PseudonymousAnalyticsController';
|
import PseudonymousAnalyticsController from './controllers/PseudonymousAnalyticsController';
|
||||||
import NewLayoutSwitcherController from './controllers/NewLayoutSwitcherController';
|
import NewLayoutSwitcherController from './controllers/NewLayoutSwitcherController';
|
||||||
|
import { ImageSize } from "./enums/ImageSize";
|
||||||
import { MetaSpace } from "../stores/spaces";
|
import { MetaSpace } from "../stores/spaces";
|
||||||
|
|
||||||
// These are just a bunch of helper arrays to avoid copy/pasting a bunch of times
|
// These are just a bunch of helper arrays to avoid copy/pasting a bunch of times
|
||||||
|
@ -737,6 +738,10 @@ export const SETTINGS: {[setting: string]: ISetting} = {
|
||||||
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||||
default: Layout.Group,
|
default: Layout.Group,
|
||||||
},
|
},
|
||||||
|
"Images.size": {
|
||||||
|
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||||
|
default: ImageSize.Normal,
|
||||||
|
},
|
||||||
"showChatEffects": {
|
"showChatEffects": {
|
||||||
supportedLevels: LEVELS_ROOM_SETTINGS_WITH_ROOM,
|
supportedLevels: LEVELS_ROOM_SETTINGS_WITH_ROOM,
|
||||||
displayName: _td("Show chat effects (animations when receiving e.g. confetti)"),
|
displayName: _td("Show chat effects (animations when receiving e.g. confetti)"),
|
||||||
|
|
|
@ -14,7 +14,7 @@ limitations under the License.
|
||||||
import SettingController from "./SettingController";
|
import SettingController from "./SettingController";
|
||||||
import { SettingLevel } from "../SettingLevel";
|
import { SettingLevel } from "../SettingLevel";
|
||||||
import SettingsStore from "../SettingsStore";
|
import SettingsStore from "../SettingsStore";
|
||||||
import { Layout } from "../Layout";
|
import { Layout } from "../enums/Layout";
|
||||||
|
|
||||||
export default class NewLayoutSwitcherController extends SettingController {
|
export default class NewLayoutSwitcherController extends SettingController {
|
||||||
public onChange(level: SettingLevel, roomId: string, newValue: any) {
|
public onChange(level: SettingLevel, roomId: string, newValue: any) {
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const SIZE_LARGE = { w: 480, h: 360 };
|
||||||
|
const SIZE_NORMAL = { w: 324, h: 220 };
|
||||||
|
|
||||||
|
export enum ImageSize {
|
||||||
|
Normal = "normal",
|
||||||
|
Large = "large",
|
||||||
|
}
|
||||||
|
|
||||||
|
export function suggestedSize(size: ImageSize): { w: number, h: number } {
|
||||||
|
switch (size) {
|
||||||
|
case ImageSize.Large:
|
||||||
|
return SIZE_LARGE;
|
||||||
|
case ImageSize.Normal:
|
||||||
|
default:
|
||||||
|
return SIZE_NORMAL;
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ import SettingsHandler from "./SettingsHandler";
|
||||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||||
import { SettingLevel } from "../SettingLevel";
|
import { SettingLevel } from "../SettingLevel";
|
||||||
import { CallbackFn, WatchManager } from "../WatchManager";
|
import { CallbackFn, WatchManager } from "../WatchManager";
|
||||||
import { Layout } from "../Layout";
|
import { Layout } from "../enums/Layout";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets and sets settings at the "device" level for the current device.
|
* Gets and sets settings at the "device" level for the current device.
|
||||||
|
|
|
@ -21,7 +21,7 @@ import { mediaFromMxc } from "../../customisations/Media";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
import { renderToStaticMarkup } from "react-dom/server";
|
import { renderToStaticMarkup } from "react-dom/server";
|
||||||
import { Layout } from "../../settings/Layout";
|
import { Layout } from "../../settings/enums/Layout";
|
||||||
import { shouldFormContinuation } from "../../components/structures/MessagePanel";
|
import { shouldFormContinuation } from "../../components/structures/MessagePanel";
|
||||||
import { formatFullDateNoDayNoTime, wantsDateSeparator } from "../../DateUtils";
|
import { formatFullDateNoDayNoTime, wantsDateSeparator } from "../../DateUtils";
|
||||||
import { RoomPermalinkCreator } from "../permalinks/Permalinks";
|
import { RoomPermalinkCreator } from "../permalinks/Permalinks";
|
||||||
|
|
|
@ -35,7 +35,7 @@ import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||||
import SpecPermalinkConstructor from "../../../../src/utils/permalinks/SpecPermalinkConstructor";
|
import SpecPermalinkConstructor from "../../../../src/utils/permalinks/SpecPermalinkConstructor";
|
||||||
import defaultDispatcher from "../../../../src/dispatcher/dispatcher";
|
import defaultDispatcher from "../../../../src/dispatcher/dispatcher";
|
||||||
import DocumentOffset from '../../../../src/editor/offset';
|
import DocumentOffset from '../../../../src/editor/offset';
|
||||||
import { Layout } from '../../../../src/settings/Layout';
|
import { Layout } from '../../../../src/settings/enums/Layout';
|
||||||
|
|
||||||
jest.mock("../../../../src/stores/RoomViewStore");
|
jest.mock("../../../../src/stores/RoomViewStore");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue