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

Add option to change the size of images/videos in the timeline #7017

Merged
merged 18 commits into from
Nov 17, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions res/css/_components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@
@import "./views/settings/_E2eAdvancedPanel.scss";
@import "./views/settings/_EmailAddresses.scss";
@import "./views/settings/_FontScalingPanel.scss";
@import "./views/settings/_ImageSizePanel.scss";
@import "./views/settings/_IntegrationManager.scss";
@import "./views/settings/_JoinRuleSettings.scss";
@import "./views/settings/_LayoutSwitcher.scss";
Expand Down
3 changes: 2 additions & 1 deletion res/css/views/messages/_MImageBody.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
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.
Expand All @@ -14,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

$timelineImageBorderRadius: 4px;
$timelineImageBorderRadius: 8px;

.mx_MImageBody_thumbnail--blurhash {
position: absolute;
Expand Down
4 changes: 2 additions & 2 deletions res/css/views/messages/_MVideoBody.scss
Original file line number Diff line number Diff line change
@@ -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");
you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,6 @@ span.mx_MVideoBody {
video.mx_MVideoBody {
max-width: 100%;
height: auto;
border-radius: 4px;
border-radius: 8px;
toger5 marked this conversation as resolved.
Show resolved Hide resolved
}
}
47 changes: 47 additions & 0 deletions res/css/views/settings/_ImageSizePanel.scss
Original file line number Diff line number Diff line change
@@ -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");
}
}
}
}
15 changes: 15 additions & 0 deletions res/img/element-icons/settings/img-size-large.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions res/img/element-icons/settings/img-size-normal.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/components/structures/FilePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import ResizeNotifier from '../../utils/ResizeNotifier';
import TimelinePanel from "./TimelinePanel";
import Spinner from "../views/elements/Spinner";
import { TileShape } from '../views/rooms/EventTile';
import { Layout } from "../../settings/Layout";
import { Layout } from "../../settings/enums/Layout";
import RoomContext, { TimelineRenderingType } from '../../contexts/RoomContext';

import { logger } from "matrix-js-sdk/src/logger";
Expand Down
2 changes: 1 addition & 1 deletion src/components/structures/MessagePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { wantsDateSeparator } from '../../DateUtils';
import { MatrixClientPeg } from '../../MatrixClientPeg';
import SettingsStore from '../../settings/SettingsStore';
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
import { Layout } from "../../settings/Layout";
import { Layout } from "../../settings/enums/Layout";
import { _t } from "../../languageHandler";
import EventTile, { haveTileForEvent, IReadReceiptProps, TileShape } from "../views/rooms/EventTile";
import { hasText } from "../../TextForEvent";
Expand Down
2 changes: 1 addition & 1 deletion src/components/structures/NotificationPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { replaceableComponent } from "../../utils/replaceableComponent";
import TimelinePanel from "./TimelinePanel";
import Spinner from "../views/elements/Spinner";
import { TileShape } from "../views/rooms/EventTile";
import { Layout } from "../../settings/Layout";
import { Layout } from "../../settings/enums/Layout";
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";

import { logger } from "matrix-js-sdk/src/logger";
Expand Down
2 changes: 1 addition & 1 deletion src/components/structures/RoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import RoomViewStore from '../../stores/RoomViewStore';
import RoomScrollStateStore, { ScrollState } from '../../stores/RoomScrollStateStore';
import WidgetEchoStore from '../../stores/WidgetEchoStore';
import SettingsStore from "../../settings/SettingsStore";
import { Layout } from "../../settings/Layout";
import { Layout } from "../../settings/enums/Layout";
import AccessibleButton from "../views/elements/AccessibleButton";
import RightPanelStore from "../../stores/RightPanelStore";
import { haveTileForEvent } from "../views/rooms/EventTile";
Expand Down
2 changes: 1 addition & 1 deletion src/components/structures/ThreadPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { ContextMenuButton } from '../../accessibility/context_menu/ContextMenuB
import ContextMenu, { useContextMenu } from './ContextMenu';
import RoomContext, { TimelineRenderingType } from '../../contexts/RoomContext';
import TimelinePanel from './TimelinePanel';
import { Layout } from '../../settings/Layout';
import { Layout } from '../../settings/enums/Layout';
import { useEventEmitter } from '../../hooks/useEventEmitter';
import AccessibleButton from '../views/elements/AccessibleButton';
import { TileShape } from '../views/rooms/EventTile';
Expand Down
2 changes: 1 addition & 1 deletion src/components/structures/ThreadView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import ResizeNotifier from '../../utils/ResizeNotifier';
import { TileShape } from '../views/rooms/EventTile';
import MessageComposer from '../views/rooms/MessageComposer';
import { RoomPermalinkCreator } from '../../utils/permalinks/Permalinks';
import { Layout } from '../../settings/Layout';
import { Layout } from '../../settings/enums/Layout';
import TimelinePanel from './TimelinePanel';
import dis from "../../dispatcher/dispatcher";
import { ActionPayload } from '../../dispatcher/payloads';
Expand Down
2 changes: 1 addition & 1 deletion src/components/structures/TimelinePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { EventType, RelationType } from 'matrix-js-sdk/src/@types/event';
import { SyncState } from 'matrix-js-sdk/src/sync.api';

import SettingsStore from "../../settings/SettingsStore";
import { Layout } from "../../settings/Layout";
import { Layout } from "../../settings/enums/Layout";
import { _t } from '../../languageHandler';
import { MatrixClientPeg } from "../../MatrixClientPeg";
import RoomContext from "../../contexts/RoomContext";
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/dialogs/ForwardDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { _t } from "../../../languageHandler";
import dis from "../../../dispatcher/dispatcher";
import { useSettingValue, useFeatureEnabled } from "../../../hooks/useSettings";
import { UIFeature } from "../../../settings/UIFeature";
import { Layout } from "../../../settings/Layout";
import { Layout } from "../../../settings/enums/Layout";
import { IDialogProps } from "./IDialogProps";
import BaseDialog from "./BaseDialog";
import { avatarUrlForUser } from "../../../Avatar";
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/elements/EventListSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import MemberAvatar from '../avatars/MemberAvatar';
import { _t } from '../../../languageHandler';
import { useStateToggle } from "../../../hooks/useStateToggle";
import AccessibleButton from "./AccessibleButton";
import { Layout } from '../../../settings/Layout';
import { Layout } from '../../../settings/enums/Layout';

interface IProps {
// An array of member events to summarise
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/elements/EventTilePreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
import * as Avatar from '../../../Avatar';
import EventTile from '../rooms/EventTile';
import SettingsStore from "../../../settings/SettingsStore";
import { Layout } from "../../../settings/Layout";
import { Layout } from "../../../settings/enums/Layout";
import { UIFeature } from "../../../settings/UIFeature";
import { replaceableComponent } from "../../../utils/replaceableComponent";
import Spinner from './Spinner';
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/elements/MemberEventListSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { Action } from '../../../dispatcher/actions';
import { SetRightPanelPhasePayload } from '../../../dispatcher/payloads/SetRightPanelPhasePayload';
import { jsxJoin } from '../../../utils/ReactUtils';
import { EventType } from 'matrix-js-sdk/src/@types/event';
import { Layout } from '../../../settings/Layout';
import { Layout } from '../../../settings/enums/Layout';

const onPinnedMessagesClick = (): void => {
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/elements/ReplyChain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import dis from '../../../dispatcher/dispatcher';
import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
import { makeUserPermalink, RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
import SettingsStore from "../../../settings/SettingsStore";
import { Layout } from "../../../settings/Layout";
import { Layout } from "../../../settings/enums/Layout";
import escapeHtml from "escape-html";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { getUserNameColorClass } from "../../../utils/FormattingUtils";
Expand Down
19 changes: 18 additions & 1 deletion src/components/views/messages/MImageBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import classNames from 'classnames';
import { CSSTransition, SwitchTransition } from 'react-transition-group';

import { logger } from "matrix-js-sdk/src/logger";
import { ImageSize } from "../../../settings/enums/ImageSize";

interface IState {
decryptedUrl?: string;
Expand All @@ -58,6 +59,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
private unmounted = true;
private image = createRef<HTMLImageElement>();
private timeout?: number;
private sizeWatcher: string;

constructor(props: IBodyProps) {
super(props);
Expand Down Expand Up @@ -317,12 +319,17 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
}
}, 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() {
this.unmounted = true;
this.context.removeListener('sync', this.onClientSync);
this.clearBlurhashTimeout();
SettingsStore.unwatchSetting(this.sizeWatcher);
}

protected messageContent(
Expand Down Expand Up @@ -368,7 +375,17 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
}

// The maximum height of the thumbnail as it is rendered as an <img>
const maxHeight = forcedHeight || Math.min((this.props.maxImageHeight || 600), infoHeight);
let maxHeight = forcedHeight;
if (!maxHeight) {
switch (SettingsStore.getValue("Images.size") as ImageSize) {
case ImageSize.Large:
maxHeight = Math.min((this.props.maxImageHeight || 600), infoHeight);
break;
case ImageSize.Normal:
default:
maxHeight = Math.min((this.props.maxImageHeight || 220), infoHeight);
}
}
// The maximum width of the thumbnail, as dictated by its natural
// maximum height.
const maxWidth = infoWidth * maxHeight / infoHeight;
Expand Down
42 changes: 37 additions & 5 deletions src/components/views/messages/MVideoBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { IBodyProps } from "./IBodyProps";
import MFileBody from "./MFileBody";

import { logger } from "matrix-js-sdk/src/logger";
import { ImageSize } from "../../../settings/enums/ImageSize";

interface IState {
decryptedUrl?: string;
Expand All @@ -42,6 +43,7 @@ interface IState {
@replaceableComponent("views.messages.MVideoBody")
export default class MVideoBody extends React.PureComponent<IBodyProps, IState> {
private videoRef = React.createRef<HTMLVideoElement>();
private sizeWatcher: string;

constructor(props) {
super(props);
Expand All @@ -57,7 +59,28 @@ 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 } {
switch (SettingsStore.getValue("Images.size") as ImageSize) {
case ImageSize.Large:
return { w: 480, h: 360 };
toger5 marked this conversation as resolved.
Show resolved Hide resolved
case ImageSize.Normal:
default:
return { w: 324, h: 220 };
}
}

private thumbScale(
fullWidth: number,
fullHeight: number,
thumbWidth?,
thumbHeight?,
toger5 marked this conversation as resolved.
Show resolved Hide resolved
) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return type plz

if (!thumbWidth || !thumbHeight) {
const dims = this.suggestedDimensions;
thumbWidth = dims.w;
thumbHeight = dims.h;
}

if (!fullWidth || !fullHeight) {
// Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even
// log this because it's spammy
Expand Down Expand Up @@ -152,12 +175,16 @@ export default class MVideoBody extends React.PureComponent<IBodyProps, IState>
}
}

async componentDidMount() {
const autoplay = SettingsStore.getValue("autoplayVideo") as boolean;
public async componentDidMount() {
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();

if (this.props.mediaEventHelper.media.isEncrypted && this.state.decryptedUrl === null) {
try {
const autoplay = SettingsStore.getValue("autoplayVideo") as boolean;
const thumbnailUrl = await this.props.mediaEventHelper.thumbnailUrl.value;
if (autoplay) {
logger.log("Preloading video");
Expand Down Expand Up @@ -189,6 +216,10 @@ export default class MVideoBody extends React.PureComponent<IBodyProps, IState>
}
}

public componentWillUnmount() {
SettingsStore.unwatchSetting(this.sizeWatcher);
}

private videoOnPlay = async () => {
if (this.hasContentUrl() || this.state.fetchingData || this.state.error) {
// We have the file, we are fetching the file, or there is an error.
Expand Down Expand Up @@ -249,8 +280,9 @@ export default class MVideoBody extends React.PureComponent<IBodyProps, IState>

const contentUrl = this.getContentUrl();
const thumbUrl = this.getThumbUrl();
let height = null;
let width = null;
const defaultDims = this.suggestedDimensions;
let height = defaultDims.h;
let width = defaultDims.w;
let poster = null;
let preload = "metadata";
if (content.info) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/rooms/EventTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { _t } from '../../../languageHandler';
import { hasText } from "../../../TextForEvent";
import * as sdk from "../../../index";
import dis from '../../../dispatcher/dispatcher';
import { Layout } from "../../../settings/Layout";
import { Layout } from "../../../settings/enums/Layout";
import { formatTime } from "../../../DateUtils";
import { MatrixClientPeg } from '../../../MatrixClientPeg';
import { ALL_RULE_TYPES } from "../../../mjolnir/BanList";
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/settings/FontScalingPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import SettingsStore from "../../../settings/SettingsStore";
import Slider from "../elements/Slider";
import { FontWatcher } from "../../../settings/watchers/FontWatcher";
import { IValidationResult, IFieldState } from '../elements/Validation';
import { Layout } from "../../../settings/Layout";
import { Layout } from "../../../settings/enums/Layout";
import { MatrixClientPeg } from '../../../MatrixClientPeg';
import { SettingLevel } from "../../../settings/SettingLevel";
import { _t } from "../../../languageHandler";
Expand Down
Loading