import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; import { computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import React from 'react'; import { Doc, StrListCast } from '../../../fields/Doc'; import { StrCast } from '../../../fields/Types'; import { AudioAnnoState } from '../../../server/SharedMediaTypes'; import { undoable } from '../../util/UndoManager'; import { ObservableReactComponent } from '../ObservableReactComponent'; import { TagItem } from '../TagsView'; import { DocumentView } from './DocumentView'; import './IconTagBox.scss'; import { Size, Toggle, ToggleType, Type } from '@dash/components'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { StyleProp } from '../StyleProp'; export interface IconTagProps { Views: DocumentView[]; IsEditing: boolean | undefined; } /** * Renders the icon tags that rest under the document. The icons rendered are determined by the values of * each icon in the userdoc. */ @observer export class IconTagBox extends ObservableReactComponent { constructor(props: IconTagProps) { super(props); makeObservable(this); } @computed get View() { return this._props.Views.lastElement(); } // prettier-ignore @computed get currentScale() { return this.View?.screenToLocalScale(); } // prettier-ignore /** * Sets or removes the specified tag * @param tag tag name (should begin with '#') * @param state flag to add or remove the metadata */ setIconTag = undoable((tag: string, state: boolean) => { this._props.Views.forEach(view => { state && TagItem.addTagToDoc(view.dataDoc, tag); !state && TagItem.removeTagFromDoc(view.dataDoc, tag); }); }, 'toggle card tag'); /** * Returns a renderable version of the button Doc that is colorized to indicate * whether the doc has the associated tag set on it or not. * @param doc doc to test * @param key metadata icon button * @returns an icon for the metdata button */ getButtonIcon = (dv: DocumentView, key: Doc): JSX.Element => { const icon = StrCast(key.icon) as IconProp; const tag = StrCast(key.toolType); const color = dv._props.styleProvider?.(dv.layoutDoc, dv.ComponentView?._props, StyleProp.FontColor) as string; return (
{' '} {/* tooltips require the wrapped item to be an element ref */} } size={Size.XSMALL} type={Type.PRIM} onClick={() => this.setIconTag(tag, !TagItem.docHasTag(this.View.Document, tag))} color={color} />
); }; /** * Displays a button to play audio annotations on the document. * NOTE: This should be generalized -- audio should * @returns */ renderAudioButtons = (dv: DocumentView, anno: string) => { const fcolor = dv._props.styleProvider?.(dv.layoutDoc, dv.ComponentView?._props, StyleProp.FontColor) as string; const audioIconColors: { [key: string]: string } = { playing: 'green', stopped: fcolor ?? 'blue', recording: 'red' }; const audioAnnoState = (audioDoc: Doc) => StrCast(audioDoc.audioAnnoState, AudioAnnoState.stopped); const color = audioIconColors[audioAnnoState(this.View.Document)]; return ( } size={Size.XSMALL} type={Type.PRIM} onClick={() => this.View?.playAnnotation()} color={color} /> ); }; /** * Renders the buttons to customize sorting depending on which group the card belongs to and the amount of total groups */ render() { const buttons = Doc.MyFilterHotKeys .map(key => ({ key, tag: StrCast(key.toolType) })) .filter(({ tag }) => this._props.IsEditing || TagItem.docHasTag(this.View.Document, tag) || (DocumentView.Selected().length === 1 && this.View.IsSelected)) .map(({ key, tag }) => ( Click to add/remove the {tag} tag}> {this.getButtonIcon(this.View, key)} )); // prettier-ignore const audioannos = StrListCast(this.View.Document[Doc.LayoutDataKey(this.View.Document) + '_audioAnnotations_text']); return !buttons.length && !audioannos.length ? null : (
{audioannos.length ? this.renderAudioButtons(this.View, audioannos.lastElement()) : null} {buttons}
); } }