Tidy up + add support for floating emoji.

This commit is contained in:
Half-Shot
2024-11-01 15:27:20 +00:00
parent fd46f8ad46
commit dfe9569720
8 changed files with 64 additions and 27 deletions

View File

@@ -1,7 +1,6 @@
.reactionPopupMenu { .reactionPopupMenu {
padding: 1em; padding: 1em;
position: absolute; position: absolute;
z-index: 99;
background: var(--cpd-color-bg-canvas-default); background: var(--cpd-color-bg-canvas-default);
top: -8em; top: -8em;
border-radius: var(--cpd-space-4x); border-radius: var(--cpd-space-4x);

View File

@@ -12,6 +12,7 @@ import {
Search, Search,
Form, Form,
} from "@vector-im/compound-web"; } from "@vector-im/compound-web";
import { ReactionIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { import {
ChangeEventHandler, ChangeEventHandler,
ComponentPropsWithoutRef, ComponentPropsWithoutRef,
@@ -46,23 +47,11 @@ const InnerButton: FC<InnerButtonProps> = ({ raised, ...props }) => {
return ( return (
<Tooltip label={t("action.send_reaction")}> <Tooltip label={t("action.send_reaction")}>
<CpdButton <CpdButton
iconOnly
kind={raised ? "primary" : "secondary"} kind={raised ? "primary" : "secondary"}
{...props} {...props}
style={{ paddingLeft: 8, paddingRight: 8 }} Icon={ReactionIcon}
> />
<p
role="img"
aria-hidden
style={{
width: "30px",
height: "0px",
display: "inline-block",
fontSize: "22px",
}}
>
</p>
</CpdButton>
</Tooltip> </Tooltip>
); );
}; };
@@ -101,14 +90,14 @@ export function ReactionPopupMenu({
<CpdButton <CpdButton
kind={isHandRaised ? "primary" : "secondary"} kind={isHandRaised ? "primary" : "secondary"}
className={styles.reactionButton} className={styles.reactionButton}
key={"raise-hand"} key="raise-hand"
onClick={() => toggleRaisedHand()} onClick={() => toggleRaisedHand()}
> >
🖐 🖐
</CpdButton> </CpdButton>
</Tooltip> </Tooltip>
</section> </section>
<div className={styles.verticalSeperator}></div> <div className={styles.verticalSeperator} />
<section> <section>
<Form.Root onSubmit={(e) => e.preventDefault()}> <Form.Root onSubmit={(e) => e.preventDefault()}>
<Search <Search
@@ -168,8 +157,7 @@ export function RaiseHandToggleButton({
const parentEventId = myMembership.eventId; const parentEventId = myMembership.eventId;
try { try {
setBusy(true); setBusy(true);
// XXX: Trying to send a unspec'd event seems to miss the 3rd overload, need to come back to this. // @ts-expect-error Trying to send a unspec'd event seems to miss the 3rd overload, need to come back to this.
// @ts-expect-error
await client.sendEvent( await client.sendEvent(
rtcSession.room.roomId, rtcSession.room.roomId,
null, null,
@@ -190,7 +178,7 @@ export function RaiseHandToggleButton({
setBusy(false); setBusy(false);
} }
}, },
[memberships, client], [memberships, client, userId, rtcSession],
); );
const toggleRaisedHand = useCallback(() => { const toggleRaisedHand = useCallback(() => {
@@ -253,13 +241,13 @@ export function RaiseHandToggleButton({
<InnerButton <InnerButton
disabled={busy} disabled={busy}
onClick={() => setShowReactionsMenu((show) => !show)} onClick={() => setShowReactionsMenu((show) => !show)}
raised={isHandRaised} raised={isHandRaised || showReactionsMenu}
/> />
{showReactionsMenu && ( {showReactionsMenu && (
<ReactionPopupMenu <ReactionPopupMenu
isHandRaised={isHandRaised} isHandRaised={isHandRaised}
canReact={canReact} canReact={canReact}
sendRelation={sendRelation} sendRelation={(reaction) => void sendRelation(reaction)}
toggleRaisedHand={toggleRaisedHand} toggleRaisedHand={toggleRaisedHand}
/> />
)} )}

View File

@@ -6,11 +6,9 @@ Please see LICENSE in the repository root for full details.
*/ */
import { ReactNode, useEffect, useState } from "react"; import { ReactNode, useEffect, useState } from "react";
import classNames from "classnames";
import "@formatjs/intl-durationformat/polyfill"; import "@formatjs/intl-durationformat/polyfill";
import { DurationFormat } from "@formatjs/intl-durationformat"; import { DurationFormat } from "@formatjs/intl-durationformat";
import styles from "./RaisedHandIndicator.module.css";
import { ReactionIndicator } from "./ReactionIndicator"; import { ReactionIndicator } from "./ReactionIndicator";
const durationFormatter = new DurationFormat(undefined, { const durationFormatter = new DurationFormat(undefined, {

View File

@@ -9,7 +9,7 @@ import { PropsWithChildren, ReactNode } from "react";
import classNames from "classnames"; import classNames from "classnames";
import "@formatjs/intl-durationformat/polyfill"; import "@formatjs/intl-durationformat/polyfill";
import styles from "./RaisedHandIndicator.module.css"; import styles from "./ReactionIndicator.module.css";
export function ReactionIndicator({ export function ReactionIndicator({
emoji, emoji,

View File

@@ -1,3 +1,12 @@
/*
Copyright 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/
import { RelationType } from "matrix-js-sdk/src/types";
import catSoundOgg from "../sound/reactions/cat.mp3?url"; import catSoundOgg from "../sound/reactions/cat.mp3?url";
import catSoundMp3 from "../sound/reactions/cat.mp3?url"; import catSoundMp3 from "../sound/reactions/cat.mp3?url";
import cricketsSoundOgg from "../sound/reactions/crickets.mp3?url"; import cricketsSoundOgg from "../sound/reactions/crickets.mp3?url";
@@ -8,7 +17,7 @@ import genericSoundOgg from "../sound/reactions/generic.mp3?url";
import genericSoundMp3 from "../sound/reactions/generic.mp3?url"; import genericSoundMp3 from "../sound/reactions/generic.mp3?url";
import lightbulbSoundOgg from "../sound/reactions/lightbulb.mp3?url"; import lightbulbSoundOgg from "../sound/reactions/lightbulb.mp3?url";
import lightbulbSoundMp3 from "../sound/reactions/lightbulb.mp3?url"; import lightbulbSoundMp3 from "../sound/reactions/lightbulb.mp3?url";
import { RelationType } from "matrix-js-sdk/src/types";
export interface ReactionOption { export interface ReactionOption {
emoji: string; emoji: string;

View File

@@ -144,3 +144,27 @@ Please see LICENSE in the repository root for full details.
position: relative; position: relative;
flex-grow: 1; flex-grow: 1;
} }
.floatingReaction {
position: relative;
z-index: 2;
font-size: 32pt;
animation-duration: 5s;
animation-name: reaction-up;
bottom: 0;
width: fit-content;
}
@keyframes reaction-up {
from {
opacity: 1;
translate: 100vw 0;
scale: 200%;
}
to {
opacity: 0;
translate: 100vw -100vh;
scale: 100%;
}
}

View File

@@ -188,6 +188,16 @@ export const InCallView: FC<InCallViewProps> = ({
[reactions], [reactions],
); );
const reactionsIcons = useMemo(
() =>
Object.entries(reactions).map(([sender, { emoji }]) => ({
sender,
emoji,
startX: -Math.ceil(Math.random() * 50) - 25,
})),
[reactions],
);
useWakeLock(); useWakeLock();
useEffect(() => { useEffect(() => {
@@ -651,6 +661,15 @@ export const InCallView: FC<InCallViewProps> = ({
</audio> </audio>
), ),
)} )}
{reactionsIcons.map(({ sender, emoji, startX }) => (
<span
style={{ left: `${startX}vw` }}
className={styles.floatingReaction}
key={sender}
>
{emoji}
</span>
))}
{footer} {footer}
{!noControls && <RageshakeRequestModal {...rageshakeRequestModalProps} />} {!noControls && <RageshakeRequestModal {...rageshakeRequestModalProps} />}
<SettingsModal <SettingsModal