mirror of https://github.com/vector-im/riot-web
Backdrop filter compatibility for Firefox and Safari
parent
27ee7c5836
commit
652ad3617d
|
@ -60,6 +60,7 @@
|
|||
"cheerio": "^1.0.0-rc.9",
|
||||
"classnames": "^2.2.6",
|
||||
"commonmark": "^0.29.3",
|
||||
"context-filter-polyfill": "^0.2.4",
|
||||
"counterpart": "^0.18.6",
|
||||
"diff-dom": "^4.2.2",
|
||||
"diff-match-patch": "^1.0.5",
|
||||
|
|
|
@ -26,6 +26,7 @@ $roomListCollapsedWidth: 68px;
|
|||
// Create a row-based flexbox for the GroupFilterPanel and the room list
|
||||
display: flex;
|
||||
contain: content;
|
||||
position: relative;
|
||||
|
||||
.mx_LeftPanel_GroupFilterPanelContainer {
|
||||
flex-grow: 0;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import React, { createRef } from "react";
|
||||
import "context-filter-polyfill";
|
||||
|
||||
interface IProps {
|
||||
width?: number;
|
||||
height?: number;
|
||||
backgroundImage?: ImageBitmap;
|
||||
backgroundImage?: CanvasImageSource;
|
||||
blur?: string;
|
||||
}
|
||||
|
||||
|
@ -31,20 +32,28 @@ export default class BackdropPanel extends React.PureComponent<IProps> {
|
|||
this.canvasRef.current.width = width;
|
||||
this.canvasRef.current.height = height;
|
||||
|
||||
const destinationX = width - backgroundImage.width;
|
||||
const destinationY = height - backgroundImage.height;
|
||||
const imageWidth = (backgroundImage as ImageBitmap).width
|
||||
|| (backgroundImage as HTMLImageElement).naturalWidth;
|
||||
const imageHeight = (backgroundImage as ImageBitmap).height
|
||||
|| (backgroundImage as HTMLImageElement).naturalHeight;
|
||||
|
||||
const destinationX = width - imageWidth;
|
||||
const destinationY = height - imageHeight;
|
||||
|
||||
this.ctx.filter = `blur(${this.props.blur})`;
|
||||
this.ctx.drawImage(
|
||||
backgroundImage,
|
||||
Math.min(destinationX, 0),
|
||||
Math.min(destinationY, 0),
|
||||
Math.max(width, backgroundImage.width),
|
||||
Math.max(height, backgroundImage.height),
|
||||
Math.max(width, imageWidth),
|
||||
Math.max(height, imageHeight),
|
||||
);
|
||||
}
|
||||
|
||||
public render() {
|
||||
return <canvas ref={this.canvasRef} className="mx_BackdropPanel" />;
|
||||
return <canvas
|
||||
ref={this.canvasRef}
|
||||
className="mx_BackdropPanel"
|
||||
/>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ import BackdropPanel from "./BackdropPanel";
|
|||
interface IProps {
|
||||
isMinimized: boolean;
|
||||
resizeNotifier: ResizeNotifier;
|
||||
backgroundImage?: ImageBitmap;
|
||||
backgroundImage?: CanvasImageSource;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
|
|
|
@ -124,7 +124,7 @@ interface IState {
|
|||
usageLimitEventTs?: number;
|
||||
useCompactLayout: boolean;
|
||||
activeCalls: Array<MatrixCall>;
|
||||
backgroundImage?: ImageBitmap;
|
||||
backgroundImage?: CanvasImageSource;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -181,7 +181,7 @@ const InnerSpacePanel = React.memo<IInnerSpacePanelProps>(({ children, isPanelCo
|
|||
});
|
||||
|
||||
interface IProps {
|
||||
backgroundImage?: ImageBitmap;
|
||||
backgroundImage?: CanvasImageSource;
|
||||
}
|
||||
|
||||
const SpacePanel = (props: IProps) => {
|
||||
|
|
|
@ -19,11 +19,12 @@ import { AsyncStoreWithClient } from "./AsyncStoreWithClient";
|
|||
import defaultDispatcher from "../dispatcher/dispatcher";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { User } from "matrix-js-sdk/src/models/user";
|
||||
import { throttle } from "lodash";
|
||||
import { memoize, throttle } from "lodash";
|
||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
||||
import { _t } from "../languageHandler";
|
||||
import {mediaFromMxc} from "../customisations/Media";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import { getDrawable } from "../utils/drawable";
|
||||
|
||||
interface IState {
|
||||
displayName?: string;
|
||||
|
@ -138,7 +139,7 @@ export class OwnProfileStore extends AsyncStoreWithClient<IState> {
|
|||
await this.updateState({displayName: profileInfo.displayname, avatarUrl: profileInfo.avatar_url});
|
||||
};
|
||||
|
||||
public async getAvatarBitmap(avatarSize = 32): Promise<ImageBitmap> {
|
||||
public async getAvatarBitmap(avatarSize = 32): Promise<CanvasImageSource> {
|
||||
let avatarUrl = this.getHttpAvatarUrl(avatarSize);
|
||||
const settingBgMxc = SettingsStore.getValue("RoomList.backgroundImage");
|
||||
if (settingBgMxc) {
|
||||
|
@ -146,14 +147,14 @@ export class OwnProfileStore extends AsyncStoreWithClient<IState> {
|
|||
}
|
||||
|
||||
if (avatarUrl) {
|
||||
const response = await fetch(avatarUrl);
|
||||
const blob = await response.blob();
|
||||
return await createImageBitmap(blob);
|
||||
return await this.buildBitmap(avatarUrl);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private buildBitmap = memoize(getDrawable);
|
||||
|
||||
private onStateEvents = throttle(async (ev: MatrixEvent) => {
|
||||
const myUserId = MatrixClientPeg.get().getUserId();
|
||||
if (ev.getType() === 'm.room.member' && ev.getSender() === myUserId && ev.getStateKey() === myUserId) {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Fetch an image using the best available method based on browser compatibility
|
||||
* @param url the URL of the image to fetch
|
||||
* @returns a canvas drawable object
|
||||
*/
|
||||
export async function getDrawable(url: string): Promise<CanvasImageSource> {
|
||||
if ('createImageBitmap' in window) {
|
||||
const response = await fetch(url);
|
||||
const blob = await response.blob();
|
||||
return await createImageBitmap(blob);
|
||||
} else {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = document.createElement("img");
|
||||
img.crossOrigin = "anonymous";
|
||||
img.onload = function() {
|
||||
resolve(img);
|
||||
}
|
||||
img.onerror = function(e) {
|
||||
reject(e);
|
||||
}
|
||||
img.src = url;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -2652,6 +2652,11 @@ content-type@^1.0.4:
|
|||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
|
||||
|
||||
context-filter-polyfill@^0.2.4:
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/context-filter-polyfill/-/context-filter-polyfill-0.2.4.tgz#ecf88d3197e7c3a47e9a7ae2d5167b703945a5d4"
|
||||
integrity sha512-LDZ3WiTzo6kIeJM7j8kPSgZf+gbD1cV1GaLyYO8RWvAg25cO3zUo3d2KizO0w9hAezNwz7tTbuWKpPdvLWzKqQ==
|
||||
|
||||
convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
|
||||
|
|
Loading…
Reference in New Issue