Properly cache blur effect

This commit is contained in:
Dariusz Niemczyk 2021-08-17 16:07:17 +02:00
parent bdb5f3bb9f
commit a999cad49d
No known key found for this signature in database
GPG key ID: 28DFE7164F497CB6
4 changed files with 58 additions and 31 deletions

View file

@ -20,6 +20,7 @@ limitations under the License.
top: 0; top: 0;
height: 100vh; height: 100vh;
width: 100%; width: 100%;
overflow: hidden;
&:before { &:before {
content: ' '; content: ' ';

View file

@ -2,10 +2,6 @@
@import "../../light/css/_paths.scss"; @import "../../light/css/_paths.scss";
@import "../../light/css/_fonts.scss"; @import "../../light/css/_fonts.scss";
@import "../../light/css/_light.scss"; @import "../../light/css/_light.scss";
// important this goes before _mods,
// as $groupFilterPanel-background-blur-amount and
// $roomlist-background-blur-amount
// are overridden in _dark.scss
@import "_dark.scss"; @import "_dark.scss";
@import "../../light/css/_mods.scss"; @import "../../light/css/_mods.scss";
@import "../../../../res/css/_components.scss"; @import "../../../../res/css/_components.scss";

View file

@ -23,48 +23,54 @@ interface IProps {
backgroundImage?: CanvasImageSource; backgroundImage?: CanvasImageSource;
} }
export default class BackdropPanel extends React.PureComponent<IProps> { interface IState {
private spacesCanvasRef = createRef<HTMLCanvasElement>(); // Left Panel image
private roomListCanvasRef = createRef<HTMLCanvasElement>(); lpImage?: string;
// Left-left panel image
llpImage?: string;
}
export default class BackdropPanel extends React.PureComponent<IProps, IState> {
private leftLeftPanelRef = createRef<HTMLCanvasElement>();
private leftPanelRef = createRef<HTMLCanvasElement>();
private sizes = { private sizes = {
spacePanelWidth: 0, leftLeftPanelWidth: 0,
roomListWidth: 0, leftPanelWidth: 0,
height: 0, height: 0,
}; };
private style = getComputedStyle(document.documentElement); private style = getComputedStyle(document.documentElement);
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
this.state = {};
} }
public componentDidMount() { public componentDidMount() {
UIStore.instance.on("SpacePanel", this.onResize); UIStore.instance.on("SpacePanel", this.onResize);
UIStore.instance.on("LeftPanel", this.onResize); UIStore.instance.on("GroupFilterPanelContainer", this.onResize);
this.onResize(); this.onResize();
} }
public componentWillUnmount() { public componentWillUnmount() {
UIStore.instance.off("SpacePanel", this.onResize); UIStore.instance.off("SpacePanel", this.onResize);
UIStore.instance.off("LeftPanel", this.onResize);
} }
public componentDidUpdate(prevProps: IProps) { public componentDidUpdate(prevProps: IProps) {
if (this.props.backgroundImage) { if (prevProps.backgroundImage !== this.props.backgroundImage) {
this.setState({});
this.onResize(); this.onResize();
} }
if (prevProps.backgroundImage && !this.props.backgroundImage) {
this.forceUpdate();
}
} }
private onResize = () => { private onResize = () => {
if (this.props.backgroundImage) { if (this.props.backgroundImage) {
const groupFilterPanelDimensions = UIStore.instance.getElementDimensions("GroupFilterPanelContainer");
const spacePanelDimensions = UIStore.instance.getElementDimensions("SpacePanel"); const spacePanelDimensions = UIStore.instance.getElementDimensions("SpacePanel");
const roomListDimensions = UIStore.instance.getElementDimensions("LeftPanel"); const roomListDimensions = UIStore.instance.getElementDimensions("LeftPanel");
this.sizes = { this.sizes = {
spacePanelWidth: spacePanelDimensions?.width ?? 0, leftLeftPanelWidth: spacePanelDimensions?.width ?? groupFilterPanelDimensions?.width ?? 0,
roomListWidth: roomListDimensions?.width ?? 0, leftPanelWidth: roomListDimensions?.width ?? 0,
height: UIStore.instance.windowHeight, height: UIStore.instance.windowHeight,
}; };
this.refreshBackdropImage(); this.refreshBackdropImage();
@ -72,10 +78,10 @@ export default class BackdropPanel extends React.PureComponent<IProps> {
}; };
private refreshBackdropImage = (): void => { private refreshBackdropImage = (): void => {
const spacesCtx = this.spacesCanvasRef.current.getContext("2d"); const spacesCtx = this.leftLeftPanelRef.current.getContext("2d");
const roomListCtx = this.roomListCanvasRef.current.getContext("2d"); const roomListCtx = this.leftPanelRef.current.getContext("2d");
const { spacePanelWidth, roomListWidth, height } = this.sizes; const { leftLeftPanelWidth, leftPanelWidth, height } = this.sizes;
const width = spacePanelWidth + roomListWidth; const width = leftLeftPanelWidth + leftPanelWidth;
const { backgroundImage } = this.props; const { backgroundImage } = this.props;
const imageWidth = (backgroundImage as ImageBitmap).width const imageWidth = (backgroundImage as ImageBitmap).width
@ -98,11 +104,11 @@ export default class BackdropPanel extends React.PureComponent<IProps> {
const x = (width - resultWidth) / 2; const x = (width - resultWidth) / 2;
const y = (height - resultHeight) / 2; const y = (height - resultHeight) / 2;
this.spacesCanvasRef.current.width = spacePanelWidth; this.leftLeftPanelRef.current.width = leftLeftPanelWidth;
this.spacesCanvasRef.current.height = height; this.leftLeftPanelRef.current.height = height;
this.roomListCanvasRef.current.width = roomListWidth; this.leftPanelRef.current.width = (window.screen.width * 0.5) - leftLeftPanelWidth;
this.roomListCanvasRef.current.height = height; this.leftPanelRef.current.height = height;
this.roomListCanvasRef.current.style.transform = `translateX(${spacePanelWidth}px)`; this.leftPanelRef.current.style.transform = `translateX(${leftLeftPanelWidth}px)`;
const spacesBlur = this.style.getPropertyValue('--roomlist-background-blur-amount'); const spacesBlur = this.style.getPropertyValue('--roomlist-background-blur-amount');
const roomListBlur = this.style.getPropertyValue('--groupFilterPanel-background-blur-amount'); const roomListBlur = this.style.getPropertyValue('--groupFilterPanel-background-blur-amount');
@ -122,29 +128,49 @@ export default class BackdropPanel extends React.PureComponent<IProps> {
backgroundImage, backgroundImage,
0, 0, 0, 0,
imageWidth, imageHeight, imageWidth, imageHeight,
x - spacePanelWidth, x - leftLeftPanelWidth,
y, y,
resultWidth, resultWidth,
resultHeight, resultHeight,
); );
this.setState({
lpImage: this.leftPanelRef.current.toDataURL('image/jpeg', 1),
llpImage: this.leftLeftPanelRef.current.toDataURL('image/jpeg', 1),
});
}; };
public render() { public render() {
if (!this.props.backgroundImage) return null; if (!this.props.backgroundImage) return null;
return <div className="mx_BackdropPanel"> return <div className="mx_BackdropPanel">
<canvas <img
ref={this.spacesCanvasRef}
className="mx_BackdropPanel--canvas" className="mx_BackdropPanel--canvas"
style={{ style={{
opacity: .19, opacity: .19,
}} }}
src={this.state.llpImage} />
<img
className="mx_BackdropPanel--canvas"
style={{
opacity: .12,
}}
src={this.state.lpImage} />
<canvas
ref={this.leftLeftPanelRef
}
className="mx_BackdropPanel--canvas"
style={{
display: this.state.lpImage ? 'none' : 'block',
opacity: .19,
}}
/> />
<canvas <canvas
style={{ style={{
display: this.state.lpImage ? 'none' : 'block',
transform: `translateX(0)`, transform: `translateX(0)`,
opacity: .12, opacity: .12,
}} }}
ref={this.roomListCanvasRef} ref={this.leftPanelRef}
className="mx_BackdropPanel--canvas" className="mx_BackdropPanel--canvas"
/> />
</div>; </div>;

View file

@ -69,6 +69,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
private ref: React.RefObject<HTMLDivElement> = createRef(); private ref: React.RefObject<HTMLDivElement> = createRef();
private listContainerRef: React.RefObject<HTMLDivElement> = createRef(); private listContainerRef: React.RefObject<HTMLDivElement> = createRef();
private groupFilterPanelWatcherRef: string; private groupFilterPanelWatcherRef: string;
private groupFilterPanelContainer = createRef<HTMLDivElement>();
private bgImageWatcherRef: string; private bgImageWatcherRef: string;
private focusedElement = null; private focusedElement = null;
private isDoingStickyHeaders = false; private isDoingStickyHeaders = false;
@ -93,6 +94,9 @@ export default class LeftPanel extends React.Component<IProps, IState> {
public componentDidMount() { public componentDidMount() {
UIStore.instance.trackElementDimensions("LeftPanel", this.ref.current); UIStore.instance.trackElementDimensions("LeftPanel", this.ref.current);
UIStore.instance.trackElementDimensions("ListContainer", this.listContainerRef.current); UIStore.instance.trackElementDimensions("ListContainer", this.listContainerRef.current);
if (this.groupFilterPanelContainer.current) {
UIStore.instance.trackElementDimensions("GroupFilterPanelContainer", this.groupFilterPanelContainer.current);
}
UIStore.instance.on("ListContainer", this.refreshStickyHeaders); UIStore.instance.on("ListContainer", this.refreshStickyHeaders);
// Using the passive option to not block the main thread // Using the passive option to not block the main thread
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
@ -420,7 +424,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
let leftLeftPanel; let leftLeftPanel;
if (this.state.showGroupFilterPanel) { if (this.state.showGroupFilterPanel) {
leftLeftPanel = ( leftLeftPanel = (
<div className="mx_LeftPanel_GroupFilterPanelContainer"> <div className="mx_LeftPanel_GroupFilterPanelContainer" ref={this.groupFilterPanelContainer}>
<GroupFilterPanel /> <GroupFilterPanel />
{ SettingsStore.getValue("feature_custom_tags") ? <CustomRoomTagPanel /> : null } { SettingsStore.getValue("feature_custom_tags") ? <CustomRoomTagPanel /> : null }
</div> </div>