Files
ThreadNet-Web/packages/shared-components/src/room/WidgetPip/WidgetPipView.tsx
T
Michael TelatynskiandGitHub b51c5ed8a7 Tweak oxlint config & delint our code (#34301)
* Remove stale max-len disablements

* Remove stale camelCase & naming-convention disablements

* Remove stale ban-ts-comment disablements

* Remove stale no-var disablements

* Remove stale no-empty-property disablements

* Remove stale react rule disablements

* Remove stale no-constant-condition disablements

* Remove stale no-unused-vars disablements

* Remove stale disablements for disabled rules

* fixup camelcase

* Remove dead code

* Tidy code

* Tweak oxlint config
2026-07-17 07:55:31 +00:00

109 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
Copyright (c) 2026 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import React, { type FC } from "react";
import { ChevronLeftIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { IconButton } from "@vector-im/compound-web";
import styles from "./WidgetPipView.module.css";
import { useViewModel, type ViewModel } from "../../core/viewmodel";
import { useI18n } from "../..";
export interface WidgetPipViewActions {
/**
* Call this once the back button is clicked in the pip view.
* The view model will handle navigating back to the associated room.
* @param ev The mouse event that triggered the back click.
*/
onBackClick: (ev: React.MouseEvent<Element, MouseEvent>) => void;
/**
* The view model exposes the `<PersistentApp />` component via this action.
* `PersistentApp` is not available in shared components.
* It can be any React component that renders a widget.
* It will be mounted inside the PipView.
*/
persistentAppComponent: React.FC<{
persistentWidgetId: string;
persistentRoomId: string;
}>;
/**
* Action that needs to be called when the pip view starts to get dragged.
* @param ev The mouse event that triggered the drag start.
*/
onStartMoving: (ev: React.MouseEvent<Element, MouseEvent>) => void;
}
export interface WidgetPipViewSnapshot {
/**
* The widget ID this view is rendering.
*/
widgetId: string;
/**
* The room name the Pip View should use in the header.
*/
roomName: string;
/**
* The room ID this PiP views widget is associated with.
*/
roomId: string;
}
/**
* The view model for the widget PiP view.
*/
export type WidgetPipViewModel = ViewModel<WidgetPipViewSnapshot> & WidgetPipViewActions;
export interface WidgetPipViewProps {
/**
* The WidgetPipViewModel to expose the WidgetPipViewSnapshot and to:
* - handling the back button callback.
* - exposing the persistentApp react component to the view.
*/
vm: WidgetPipViewModel;
/**
* The avatar is passed as a React component.
* This allows any avatar implementation to be used in this view (like RoomAvatar).
*/
// In the future the avatar component can/should also become a shared component.
// It would then be accessible in the shared component package and we could remove this prop.
RoomAvatar: React.FC<{ size: string }>;
}
/**
* A picture-in-picture view for a widget. Additional controls are shown if the
* widget represents a call.
*/
export const WidgetPipView: FC<WidgetPipViewProps> = ({ vm, RoomAvatar }) => {
const snapshot = useViewModel(vm);
const { translate: _t } = useI18n();
return (
// The interaction where we use the `onMouseDown` handler is only useful for dragging the widget around,
// which is not possible via the keyboard. The outcome of this interaction can only be changed
// if the user interacts with a mouse. Hence there is no use in providing an accessible alternative.
// In the future we might consider introducing alternative shortcuts for moving the PiP around
// with the keyboard.
<div data-testid="widget-pip-container" className={styles.container} onMouseDown={vm.onStartMoving}>
<div className={styles.header}>
<IconButton
size="28px"
data-testid="base-card-back-button"
onClick={(ev) => vm.onBackClick(ev)}
tooltip={_t("action|back")}
kind="secondary"
>
<ChevronLeftIcon />
</IconButton>
<RoomAvatar size="20px" />
{snapshot.roomName}
</div>
<div className={styles.roundedCornerContainer}>
<vm.persistentAppComponent persistentWidgetId={snapshot.widgetId} persistentRoomId={snapshot.roomId} />
</div>
</div>
);
};