Merge branch 'develop' of github.com:matrix-org/matrix-react-sdk into t3chguy/fix/18091
Conflicts: src/components/structures/SpaceRoomView.tsx
This commit is contained in:
commit
2114e854f9
131 changed files with 929 additions and 505 deletions
|
@ -122,7 +122,7 @@ export default class AddressTile extends React.Component<IProps> {
|
|||
let dismiss;
|
||||
if (this.props.canDismiss) {
|
||||
dismiss = (
|
||||
<div className="mx_AddressTile_dismiss" onClick={this.props.onDismissed} >
|
||||
<div className="mx_AddressTile_dismiss" onClick={this.props.onDismissed}>
|
||||
<img src={require("../../../../res/img/icon-address-delete.svg")} width="9" height="9" />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -51,7 +51,8 @@ export class ExistingSource extends React.Component<DesktopCapturerSourceIProps>
|
|||
<AccessibleButton
|
||||
className="mx_desktopCapturerSourcePicker_stream_button"
|
||||
title={this.props.source.name}
|
||||
onClick={this.onClick} >
|
||||
onClick={this.onClick}
|
||||
>
|
||||
<img
|
||||
className="mx_desktopCapturerSourcePicker_stream_thumbnail"
|
||||
src={this.props.source.thumbnailURL}
|
||||
|
|
|
@ -160,41 +160,80 @@ export default class ImageView extends React.Component<IProps, IState> {
|
|||
});
|
||||
};
|
||||
|
||||
private zoom(delta: number) {
|
||||
const newZoom = this.state.zoom + delta;
|
||||
private zoomDelta(delta: number, anchorX?: number, anchorY?: number) {
|
||||
this.zoom(this.state.zoom + delta, anchorX, anchorY);
|
||||
}
|
||||
|
||||
private zoom(zoomLevel: number, anchorX?: number, anchorY?: number) {
|
||||
const oldZoom = this.state.zoom;
|
||||
const newZoom = Math.min(zoomLevel, this.state.maxZoom);
|
||||
|
||||
if (newZoom <= this.state.minZoom) {
|
||||
// Zoom out fully
|
||||
this.setState({
|
||||
zoom: this.state.minZoom,
|
||||
translationX: 0,
|
||||
translationY: 0,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (newZoom >= this.state.maxZoom) {
|
||||
this.setState({ zoom: this.state.maxZoom });
|
||||
return;
|
||||
}
|
||||
} else if (typeof anchorX !== "number" && typeof anchorY !== "number") {
|
||||
// Zoom relative to the center of the view
|
||||
this.setState({
|
||||
zoom: newZoom,
|
||||
translationX: this.state.translationX * newZoom / oldZoom,
|
||||
translationY: this.state.translationY * newZoom / oldZoom,
|
||||
});
|
||||
} else {
|
||||
// Zoom relative to the given point on the image.
|
||||
// First we need to figure out the offset of the anchor point
|
||||
// relative to the center of the image, accounting for rotation.
|
||||
let offsetX;
|
||||
let offsetY;
|
||||
// The modulo operator can return negative values for some
|
||||
// rotations, so we have to do some extra work to normalize it
|
||||
switch (((this.state.rotation % 360) + 360) % 360) {
|
||||
case 0:
|
||||
offsetX = this.image.current.clientWidth / 2 - anchorX;
|
||||
offsetY = this.image.current.clientHeight / 2 - anchorY;
|
||||
break;
|
||||
case 90:
|
||||
offsetX = anchorY - this.image.current.clientHeight / 2;
|
||||
offsetY = this.image.current.clientWidth / 2 - anchorX;
|
||||
break;
|
||||
case 180:
|
||||
offsetX = anchorX - this.image.current.clientWidth / 2;
|
||||
offsetY = anchorY - this.image.current.clientHeight / 2;
|
||||
break;
|
||||
case 270:
|
||||
offsetX = this.image.current.clientHeight / 2 - anchorY;
|
||||
offsetY = anchorX - this.image.current.clientWidth / 2;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
zoom: newZoom,
|
||||
});
|
||||
// Apply the zoom and offset
|
||||
this.setState({
|
||||
zoom: newZoom,
|
||||
translationX: this.state.translationX + (newZoom - oldZoom) * offsetX,
|
||||
translationY: this.state.translationY + (newZoom - oldZoom) * offsetY,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private onWheel = (ev: WheelEvent) => {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
if (ev.target === this.image.current) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
|
||||
const { deltaY } = normalizeWheelEvent(ev);
|
||||
this.zoom(-(deltaY * ZOOM_COEFFICIENT));
|
||||
const { deltaY } = normalizeWheelEvent(ev);
|
||||
// Zoom in on the point on the image targeted by the cursor
|
||||
this.zoomDelta(-deltaY * ZOOM_COEFFICIENT, ev.offsetX, ev.offsetY);
|
||||
}
|
||||
};
|
||||
|
||||
private onZoomInClick = () => {
|
||||
this.zoom(ZOOM_STEP);
|
||||
this.zoomDelta(ZOOM_STEP);
|
||||
};
|
||||
|
||||
private onZoomOutClick = () => {
|
||||
this.zoom(-ZOOM_STEP);
|
||||
this.zoomDelta(-ZOOM_STEP);
|
||||
};
|
||||
|
||||
private onKeyDown = (ev: KeyboardEvent) => {
|
||||
|
@ -259,7 +298,7 @@ export default class ImageView extends React.Component<IProps, IState> {
|
|||
|
||||
// Zoom in if we are completely zoomed out
|
||||
if (this.state.zoom === this.state.minZoom) {
|
||||
this.setState({ zoom: this.state.maxZoom });
|
||||
this.zoom(this.state.maxZoom, ev.nativeEvent.offsetX, ev.nativeEvent.offsetY);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -289,11 +328,7 @@ export default class ImageView extends React.Component<IProps, IState> {
|
|||
Math.abs(this.state.translationX - this.previousX) < ZOOM_DISTANCE &&
|
||||
Math.abs(this.state.translationY - this.previousY) < ZOOM_DISTANCE
|
||||
) {
|
||||
this.setState({
|
||||
zoom: this.state.minZoom,
|
||||
translationX: 0,
|
||||
translationY: 0,
|
||||
});
|
||||
this.zoom(this.state.minZoom);
|
||||
this.initX = 0;
|
||||
this.initY = 0;
|
||||
}
|
||||
|
@ -384,7 +419,8 @@ export default class ImageView extends React.Component<IProps, IState> {
|
|||
const avatar = (
|
||||
<MemberAvatar
|
||||
member={mxEvent.sender}
|
||||
width={32} height={32}
|
||||
width={32}
|
||||
height={32}
|
||||
viewUserOnClick={true}
|
||||
/>
|
||||
);
|
||||
|
@ -403,7 +439,7 @@ export default class ImageView extends React.Component<IProps, IState> {
|
|||
// an empty div here, since the panel uses space-between
|
||||
// and we want the same placement of elements
|
||||
info = (
|
||||
<div></div>
|
||||
<div />
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -427,15 +463,15 @@ export default class ImageView extends React.Component<IProps, IState> {
|
|||
<AccessibleTooltipButton
|
||||
className="mx_ImageView_button mx_ImageView_button_zoomOut"
|
||||
title={_t("Zoom out")}
|
||||
onClick={this.onZoomOutClick}>
|
||||
</AccessibleTooltipButton>
|
||||
onClick={this.onZoomOutClick}
|
||||
/>
|
||||
);
|
||||
zoomInButton = (
|
||||
<AccessibleTooltipButton
|
||||
className="mx_ImageView_button mx_ImageView_button_zoomIn"
|
||||
title={_t("Zoom in")}
|
||||
onClick={this.onZoomInClick}>
|
||||
</AccessibleTooltipButton>
|
||||
onClick={this.onZoomInClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -457,24 +493,24 @@ export default class ImageView extends React.Component<IProps, IState> {
|
|||
<AccessibleTooltipButton
|
||||
className="mx_ImageView_button mx_ImageView_button_rotateCCW"
|
||||
title={_t("Rotate Left")}
|
||||
onClick={this.onRotateCounterClockwiseClick}>
|
||||
</AccessibleTooltipButton>
|
||||
onClick={this.onRotateCounterClockwiseClick}
|
||||
/>
|
||||
<AccessibleTooltipButton
|
||||
className="mx_ImageView_button mx_ImageView_button_rotateCW"
|
||||
title={_t("Rotate Right")}
|
||||
onClick={this.onRotateClockwiseClick}>
|
||||
</AccessibleTooltipButton>
|
||||
onClick={this.onRotateClockwiseClick}
|
||||
/>
|
||||
<AccessibleTooltipButton
|
||||
className="mx_ImageView_button mx_ImageView_button_download"
|
||||
title={_t("Download")}
|
||||
onClick={this.onDownloadClick}>
|
||||
</AccessibleTooltipButton>
|
||||
onClick={this.onDownloadClick}
|
||||
/>
|
||||
{ contextMenuButton }
|
||||
<AccessibleTooltipButton
|
||||
className="mx_ImageView_button mx_ImageView_button_close"
|
||||
title={_t("Close")}
|
||||
onClick={this.props.onFinished}>
|
||||
</AccessibleTooltipButton>
|
||||
onClick={this.props.onFinished}
|
||||
/>
|
||||
{ this.renderContextMenu() }
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -92,7 +92,7 @@ const MiniAvatarUploader: React.FC<IProps> = ({ hasAvatar, hasAvatarLabel, noAva
|
|||
<div className="mx_MiniAvatarUploader_indicator">
|
||||
{ busy ?
|
||||
<Spinner w={20} h={20} /> :
|
||||
<div className="mx_MiniAvatarUploader_cameraIcon"></div> }
|
||||
<div className="mx_MiniAvatarUploader_cameraIcon" /> }
|
||||
</div>
|
||||
|
||||
<div className={classNames("mx_Tooltip", {
|
||||
|
|
|
@ -258,7 +258,10 @@ class Pill extends React.Component {
|
|||
linkText = groupId;
|
||||
if (this.props.shouldShowPillAvatar) {
|
||||
avatar = <BaseAvatar
|
||||
name={name || groupId} width={16} height={16} aria-hidden="true"
|
||||
name={name || groupId}
|
||||
width={16}
|
||||
height={16}
|
||||
aria-hidden="true"
|
||||
url={avatarUrl ? mediaFromMxc(avatarUrl).getSquareThumbnailHttp(16) : null} />;
|
||||
}
|
||||
pillClass = 'mx_GroupPill';
|
||||
|
|
|
@ -134,8 +134,10 @@ export default class PowerSelector extends React.Component {
|
|||
const label = typeof this.props.label === "undefined" ? _t("Power level") : this.props.label;
|
||||
if (this.state.custom) {
|
||||
picker = (
|
||||
<Field type="number"
|
||||
label={label} max={this.props.maxValue}
|
||||
<Field
|
||||
type="number"
|
||||
label={label}
|
||||
max={this.props.maxValue}
|
||||
onBlur={this.onCustomBlur}
|
||||
onKeyDown={this.onCustomKeyDown}
|
||||
onChange={this.onCustomChange}
|
||||
|
@ -157,9 +159,12 @@ export default class PowerSelector extends React.Component {
|
|||
});
|
||||
|
||||
picker = (
|
||||
<Field element="select"
|
||||
label={label} onChange={this.onSelectChange}
|
||||
value={String(this.state.selectValue)} disabled={this.props.disabled}
|
||||
<Field
|
||||
element="select"
|
||||
label={label}
|
||||
onChange={this.onSelectChange}
|
||||
value={String(this.state.selectValue)}
|
||||
disabled={this.props.disabled}
|
||||
>
|
||||
{ options }
|
||||
</Field>
|
||||
|
|
|
@ -166,8 +166,7 @@ export default class Tooltip extends React.Component<IProps> {
|
|||
public render() {
|
||||
// Render a placeholder
|
||||
return (
|
||||
<div className={this.props.className}>
|
||||
</div>
|
||||
<div className={this.props.className} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue