mirror of
https://github.com/element-hq/element-web
synced 2024-11-25 10:45:51 +03:00
Move backdrop filter to a canvas based solution
This commit is contained in:
parent
f0ad70f0e7
commit
27ee7c5836
9 changed files with 129 additions and 49 deletions
|
@ -43,7 +43,6 @@ $roomListCollapsedWidth: 68px;
|
||||||
// Note: The 'room list' in this context is actually everything that isn't the tag
|
// Note: The 'room list' in this context is actually everything that isn't the tag
|
||||||
// panel, such as the menu options, breadcrumbs, filtering, etc
|
// panel, such as the menu options, breadcrumbs, filtering, etc
|
||||||
.mx_LeftPanel_roomListContainer {
|
.mx_LeftPanel_roomListContainer {
|
||||||
background-color: $roomlist-bg-color;
|
|
||||||
flex: 1 0 0;
|
flex: 1 0 0;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
// Create another flexbox (this time a column) for the room list components
|
// Create another flexbox (this time a column) for the room list components
|
||||||
|
|
|
@ -35,6 +35,16 @@ limitations under the License.
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_BackdropPanel {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
z-index: 0;
|
||||||
|
opacity: .15;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_MatrixToolbar {
|
.mx_MatrixToolbar {
|
||||||
order: 1;
|
order: 1;
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ $activeBorderColor: $secondary-fg-color;
|
||||||
background-color: $groupFilterPanel-bg-color;
|
background-color: $groupFilterPanel-bg-color;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
// Create another flexbox so the Panel fills the container
|
// Create another flexbox so the Panel fills the container
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -4,27 +4,6 @@
|
||||||
// set the user avatar (if any) as a background so
|
// set the user avatar (if any) as a background so
|
||||||
// it can be blurred by the tag panel and room list
|
// it can be blurred by the tag panel and room list
|
||||||
|
|
||||||
@supports (backdrop-filter: none) {
|
|
||||||
.mx_LeftPanel {
|
|
||||||
background-image: var(--avatar-url, unset);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: cover;
|
|
||||||
background-position: left top;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_GroupFilterPanel {
|
|
||||||
backdrop-filter: blur($groupFilterPanel-background-blur-amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_SpacePanel {
|
|
||||||
backdrop-filter: blur($groupFilterPanel-background-blur-amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_LeftPanel .mx_LeftPanel_roomListContainer {
|
|
||||||
backdrop-filter: blur($roomlist-background-blur-amount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomSublist_showNButton {
|
.mx_RoomSublist_showNButton {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
50
src/components/structures/BackdropPanel.tsx
Normal file
50
src/components/structures/BackdropPanel.tsx
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import React, { createRef } from "react";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
backgroundImage?: ImageBitmap;
|
||||||
|
blur?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default class BackdropPanel extends React.PureComponent<IProps> {
|
||||||
|
private canvasRef: React.RefObject<HTMLCanvasElement> = createRef();
|
||||||
|
private ctx: CanvasRenderingContext2D;
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
blur: "60px",
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentDidMount() {
|
||||||
|
this.ctx = this.canvasRef.current.getContext("2d");
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentDidUpdate() {
|
||||||
|
if (this.props.backgroundImage) {
|
||||||
|
requestAnimationFrame(this.refreshBackdropImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private refreshBackdropImage = (): void => {
|
||||||
|
const { width, height, backgroundImage } = this.props;
|
||||||
|
this.canvasRef.current.width = width;
|
||||||
|
this.canvasRef.current.height = height;
|
||||||
|
|
||||||
|
const destinationX = width - backgroundImage.width;
|
||||||
|
const destinationY = height - backgroundImage.height;
|
||||||
|
|
||||||
|
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),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
return <canvas ref={this.canvasRef} className="mx_BackdropPanel" />;
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,18 +36,18 @@ import SettingsStore from "../../settings/SettingsStore";
|
||||||
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../stores/room-list/RoomListStore";
|
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../stores/room-list/RoomListStore";
|
||||||
import IndicatorScrollbar from "../structures/IndicatorScrollbar";
|
import IndicatorScrollbar from "../structures/IndicatorScrollbar";
|
||||||
import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
|
import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
|
||||||
import { OwnProfileStore } from "../../stores/OwnProfileStore";
|
|
||||||
import RoomListNumResults from "../views/rooms/RoomListNumResults";
|
import RoomListNumResults from "../views/rooms/RoomListNumResults";
|
||||||
import LeftPanelWidget from "./LeftPanelWidget";
|
import LeftPanelWidget from "./LeftPanelWidget";
|
||||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||||
import {mediaFromMxc} from "../../customisations/Media";
|
|
||||||
import SpaceStore, {UPDATE_SELECTED_SPACE} from "../../stores/SpaceStore";
|
import SpaceStore, {UPDATE_SELECTED_SPACE} from "../../stores/SpaceStore";
|
||||||
import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager";
|
import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager";
|
||||||
import UIStore from "../../stores/UIStore";
|
import UIStore from "../../stores/UIStore";
|
||||||
|
import BackdropPanel from "./BackdropPanel";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
isMinimized: boolean;
|
isMinimized: boolean;
|
||||||
resizeNotifier: ResizeNotifier;
|
resizeNotifier: ResizeNotifier;
|
||||||
|
backgroundImage?: ImageBitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
|
@ -85,16 +85,14 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
BreadcrumbsStore.instance.on(UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
BreadcrumbsStore.instance.on(UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
||||||
RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
||||||
OwnProfileStore.instance.on(UPDATE_EVENT, this.onBackgroundImageUpdate);
|
|
||||||
SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.updateActiveSpace);
|
SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.updateActiveSpace);
|
||||||
this.bgImageWatcherRef = SettingsStore.watchSetting(
|
|
||||||
"RoomList.backgroundImage", null, this.onBackgroundImageUpdate);
|
|
||||||
this.groupFilterPanelWatcherRef = SettingsStore.watchSetting("TagPanel.enableTagPanel", null, () => {
|
this.groupFilterPanelWatcherRef = SettingsStore.watchSetting("TagPanel.enableTagPanel", null, () => {
|
||||||
this.setState({showGroupFilterPanel: SettingsStore.getValue("TagPanel.enableTagPanel")});
|
this.setState({showGroupFilterPanel: SettingsStore.getValue("TagPanel.enableTagPanel")});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
|
UIStore.instance.trackElementDimensions("LeftPanel", this.ref.current);
|
||||||
UIStore.instance.trackElementDimensions("ListContainer", this.listContainerRef.current);
|
UIStore.instance.trackElementDimensions("ListContainer", this.listContainerRef.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
|
||||||
|
@ -104,10 +102,8 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
SettingsStore.unwatchSetting(this.groupFilterPanelWatcherRef);
|
SettingsStore.unwatchSetting(this.groupFilterPanelWatcherRef);
|
||||||
SettingsStore.unwatchSetting(this.bgImageWatcherRef);
|
|
||||||
BreadcrumbsStore.instance.off(UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
BreadcrumbsStore.instance.off(UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
||||||
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
||||||
OwnProfileStore.instance.off(UPDATE_EVENT, this.onBackgroundImageUpdate);
|
|
||||||
SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.updateActiveSpace);
|
SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.updateActiveSpace);
|
||||||
UIStore.instance.stopTrackingElementDimensions("ListContainer");
|
UIStore.instance.stopTrackingElementDimensions("ListContainer");
|
||||||
UIStore.instance.removeListener("ListContainer", this.refreshStickyHeaders);
|
UIStore.instance.removeListener("ListContainer", this.refreshStickyHeaders);
|
||||||
|
@ -144,23 +140,6 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private onBackgroundImageUpdate = () => {
|
|
||||||
// Note: we do this in the LeftPanel as it uses this variable most prominently.
|
|
||||||
const avatarSize = 32; // arbitrary
|
|
||||||
let avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize);
|
|
||||||
const settingBgMxc = SettingsStore.getValue("RoomList.backgroundImage");
|
|
||||||
if (settingBgMxc) {
|
|
||||||
avatarUrl = mediaFromMxc(settingBgMxc).getSquareThumbnailHttp(avatarSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
const avatarUrlProp = `url(${avatarUrl})`;
|
|
||||||
if (!avatarUrl) {
|
|
||||||
document.body.style.removeProperty("--avatar-url");
|
|
||||||
} else if (document.body.style.getPropertyValue("--avatar-url") !== avatarUrlProp) {
|
|
||||||
document.body.style.setProperty("--avatar-url", avatarUrlProp);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private handleStickyHeaders(list: HTMLDivElement) {
|
private handleStickyHeaders(list: HTMLDivElement) {
|
||||||
if (this.isDoingStickyHeaders) return;
|
if (this.isDoingStickyHeaders) return;
|
||||||
this.isDoingStickyHeaders = true;
|
this.isDoingStickyHeaders = true;
|
||||||
|
@ -453,8 +432,15 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
"mx_AutoHideScrollbar",
|
"mx_AutoHideScrollbar",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const panelDimensions = UIStore.instance.getElementDimensions("LeftPanel");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={containerClasses} ref={this.ref}>
|
<div className={containerClasses} ref={this.ref}>
|
||||||
|
<BackdropPanel
|
||||||
|
backgroundImage={this.props.backgroundImage}
|
||||||
|
width={panelDimensions?.width}
|
||||||
|
height={panelDimensions?.height}
|
||||||
|
/>
|
||||||
{leftLeftPanel}
|
{leftLeftPanel}
|
||||||
<aside className="mx_LeftPanel_roomListContainer">
|
<aside className="mx_LeftPanel_roomListContainer">
|
||||||
{this.renderHeader()}
|
{this.renderHeader()}
|
||||||
|
|
|
@ -59,6 +59,10 @@ import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||||
import CallHandler, { CallHandlerEvent } from '../../CallHandler';
|
import CallHandler, { CallHandlerEvent } from '../../CallHandler';
|
||||||
import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
|
import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
|
||||||
import AudioFeedArrayForCall from '../views/voip/AudioFeedArrayForCall';
|
import AudioFeedArrayForCall from '../views/voip/AudioFeedArrayForCall';
|
||||||
|
import { OwnProfileStore } from '../../stores/OwnProfileStore';
|
||||||
|
import { UPDATE_EVENT } from "../../stores/AsyncStore";
|
||||||
|
import { mediaFromMxc } from "../../customisations/Media";
|
||||||
|
|
||||||
|
|
||||||
// We need to fetch each pinned message individually (if we don't already have it)
|
// We need to fetch each pinned message individually (if we don't already have it)
|
||||||
// so each pinned message may trigger a request. Limit the number per room for sanity.
|
// so each pinned message may trigger a request. Limit the number per room for sanity.
|
||||||
|
@ -120,6 +124,7 @@ interface IState {
|
||||||
usageLimitEventTs?: number;
|
usageLimitEventTs?: number;
|
||||||
useCompactLayout: boolean;
|
useCompactLayout: boolean;
|
||||||
activeCalls: Array<MatrixCall>;
|
activeCalls: Array<MatrixCall>;
|
||||||
|
backgroundImage?: ImageBitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -198,6 +203,8 @@ class LoggedInView extends React.Component<IProps, IState> {
|
||||||
this.resizer = this._createResizer();
|
this.resizer = this._createResizer();
|
||||||
this.resizer.attach();
|
this.resizer.attach();
|
||||||
this._loadResizerPreferences();
|
this._loadResizerPreferences();
|
||||||
|
|
||||||
|
OwnProfileStore.instance.on(UPDATE_EVENT, this.refreshBackgroundImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
@ -206,10 +213,17 @@ class LoggedInView extends React.Component<IProps, IState> {
|
||||||
this._matrixClient.removeListener("accountData", this.onAccountData);
|
this._matrixClient.removeListener("accountData", this.onAccountData);
|
||||||
this._matrixClient.removeListener("sync", this.onSync);
|
this._matrixClient.removeListener("sync", this.onSync);
|
||||||
this._matrixClient.removeListener("RoomState.events", this.onRoomStateEvents);
|
this._matrixClient.removeListener("RoomState.events", this.onRoomStateEvents);
|
||||||
|
OwnProfileStore.instance.off(UPDATE_EVENT, this.refreshBackgroundImage);
|
||||||
SettingsStore.unwatchSetting(this.compactLayoutWatcherRef);
|
SettingsStore.unwatchSetting(this.compactLayoutWatcherRef);
|
||||||
this.resizer.detach();
|
this.resizer.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private refreshBackgroundImage = async (): Promise<void> => {
|
||||||
|
this.setState({
|
||||||
|
backgroundImage: await OwnProfileStore.instance.getAvatarBitmap(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private onCallsChanged = () => {
|
private onCallsChanged = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
activeCalls: CallHandler.sharedInstance().getAllActiveCalls(),
|
activeCalls: CallHandler.sharedInstance().getAllActiveCalls(),
|
||||||
|
@ -633,10 +647,13 @@ class LoggedInView extends React.Component<IProps, IState> {
|
||||||
>
|
>
|
||||||
<ToastContainer />
|
<ToastContainer />
|
||||||
<div ref={this._resizeContainer} className={bodyClasses}>
|
<div ref={this._resizeContainer} className={bodyClasses}>
|
||||||
{ SettingsStore.getValue("feature_spaces") ? <SpacePanel /> : null }
|
{ SettingsStore.getValue("feature_spaces")
|
||||||
|
? <SpacePanel backgroundImage={this.state.backgroundImage} />
|
||||||
|
: null }
|
||||||
<LeftPanel
|
<LeftPanel
|
||||||
isMinimized={this.props.collapseLhs || false}
|
isMinimized={this.props.collapseLhs || false}
|
||||||
resizeNotifier={this.props.resizeNotifier}
|
resizeNotifier={this.props.resizeNotifier}
|
||||||
|
backgroundImage={this.state.backgroundImage}
|
||||||
/>
|
/>
|
||||||
<ResizeHandle />
|
<ResizeHandle />
|
||||||
{ pageElement }
|
{ pageElement }
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { Dispatch, ReactNode, SetStateAction, useEffect, useState } from "react";
|
import React, { Dispatch, ReactNode, SetStateAction, useEffect, useRef, useState } from "react";
|
||||||
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
|
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
|
@ -43,6 +43,8 @@ import { Key } from "../../../Keyboard";
|
||||||
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
||||||
import { NotificationState } from "../../../stores/notifications/NotificationState";
|
import { NotificationState } from "../../../stores/notifications/NotificationState";
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
import BackdropPanel from "../../structures/BackdropPanel";
|
||||||
|
import UIStore from "../../../stores/UIStore";
|
||||||
|
|
||||||
interface IButtonProps {
|
interface IButtonProps {
|
||||||
space?: Room;
|
space?: Room;
|
||||||
|
@ -178,7 +180,11 @@ const InnerSpacePanel = React.memo<IInnerSpacePanelProps>(({ children, isPanelCo
|
||||||
</div>;
|
</div>;
|
||||||
});
|
});
|
||||||
|
|
||||||
const SpacePanel = () => {
|
interface IProps {
|
||||||
|
backgroundImage?: ImageBitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SpacePanel = (props: IProps) => {
|
||||||
// We don't need the handle as we position the menu in a constant location
|
// We don't need the handle as we position the menu in a constant location
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu<void>();
|
const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu<void>();
|
||||||
|
@ -261,6 +267,15 @@ const SpacePanel = () => {
|
||||||
openMenu();
|
openMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ref: React.RefObject<HTMLUListElement> = useRef(null);
|
||||||
|
useEffect(() => {
|
||||||
|
UIStore.instance.trackElementDimensions("SpacePanel", ref.current);
|
||||||
|
return () => {
|
||||||
|
UIStore.instance.stopTrackingElementDimensions("SpacePanel");
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
const panelDimensions = UIStore.instance.getElementDimensions("SpacePanel");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DragDropContext onDragEnd={result => {
|
<DragDropContext onDragEnd={result => {
|
||||||
if (!result.destination) return; // dropped outside the list
|
if (!result.destination) return; // dropped outside the list
|
||||||
|
@ -271,7 +286,13 @@ const SpacePanel = () => {
|
||||||
<ul
|
<ul
|
||||||
className={classNames("mx_SpacePanel", { collapsed: isPanelCollapsed })}
|
className={classNames("mx_SpacePanel", { collapsed: isPanelCollapsed })}
|
||||||
onKeyDown={onKeyDownHandler}
|
onKeyDown={onKeyDownHandler}
|
||||||
|
ref={ref}
|
||||||
>
|
>
|
||||||
|
<BackdropPanel
|
||||||
|
backgroundImage={props.backgroundImage}
|
||||||
|
width={panelDimensions?.width}
|
||||||
|
height={panelDimensions?.height}
|
||||||
|
/>
|
||||||
<Droppable droppableId="top-level-spaces">
|
<Droppable droppableId="top-level-spaces">
|
||||||
{(provided, snapshot) => (
|
{(provided, snapshot) => (
|
||||||
<AutoHideScrollbar
|
<AutoHideScrollbar
|
||||||
|
|
|
@ -23,6 +23,7 @@ import { throttle } from "lodash";
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
import { MatrixClientPeg } from "../MatrixClientPeg";
|
||||||
import { _t } from "../languageHandler";
|
import { _t } from "../languageHandler";
|
||||||
import {mediaFromMxc} from "../customisations/Media";
|
import {mediaFromMxc} from "../customisations/Media";
|
||||||
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
displayName?: string;
|
displayName?: string;
|
||||||
|
@ -137,6 +138,22 @@ export class OwnProfileStore extends AsyncStoreWithClient<IState> {
|
||||||
await this.updateState({displayName: profileInfo.displayname, avatarUrl: profileInfo.avatar_url});
|
await this.updateState({displayName: profileInfo.displayname, avatarUrl: profileInfo.avatar_url});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public async getAvatarBitmap(avatarSize = 32): Promise<ImageBitmap> {
|
||||||
|
let avatarUrl = this.getHttpAvatarUrl(avatarSize);
|
||||||
|
const settingBgMxc = SettingsStore.getValue("RoomList.backgroundImage");
|
||||||
|
if (settingBgMxc) {
|
||||||
|
avatarUrl = mediaFromMxc(settingBgMxc).getSquareThumbnailHttp(avatarSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avatarUrl) {
|
||||||
|
const response = await fetch(avatarUrl);
|
||||||
|
const blob = await response.blob();
|
||||||
|
return await createImageBitmap(blob);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private onStateEvents = throttle(async (ev: MatrixEvent) => {
|
private onStateEvents = throttle(async (ev: MatrixEvent) => {
|
||||||
const myUserId = MatrixClientPeg.get().getUserId();
|
const myUserId = MatrixClientPeg.get().getUserId();
|
||||||
if (ev.getType() === 'm.room.member' && ev.getSender() === myUserId && ev.getStateKey() === myUserId) {
|
if (ev.getType() === 'm.room.member' && ev.getSender() === myUserId && ev.getStateKey() === myUserId) {
|
||||||
|
|
Loading…
Reference in a new issue