You've already forked matrix-react-sdk
							
							
				mirror of
				https://github.com/matrix-org/matrix-react-sdk.git
				synced 2025-11-03 00:33:22 +03:00 
			
		
		
		
	Backdrop filter compatibility for Firefox and Safari
This commit is contained in:
		@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								src/utils/drawable.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/utils/drawable.ts
									
									
									
									
									
										Normal file
									
								
							@@ -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"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user