Merge pull request #321 from vector-im/dbkr/ptt_mobile_touch_prompt

Fix hold-to-speak and prompt text on mobile
This commit is contained in:
David Baker 2022-05-12 12:16:48 +01:00 committed by GitHub
commit 9fbe4278c2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 90 additions and 20 deletions

View file

@ -43,23 +43,50 @@ export const PTTButton: React.FC<Props> = ({
stopTalking, stopTalking,
}) => { }) => {
const [isHeld, setHeld] = useState(false); const [isHeld, setHeld] = useState(false);
const onDocumentMouseUp = useCallback(() => { const onWindowMouseUp = useCallback(
if (isHeld) stopTalking(); (e) => {
setHeld(false); if (isHeld) stopTalking();
}, [isHeld, setHeld, stopTalking]); setHeld(false);
},
[isHeld, setHeld, stopTalking]
);
const onButtonMouseDown = useCallback(() => { const onWindowTouchEnd = useCallback(
setHeld(true); (e: TouchEvent) => {
startTalking(); e.preventDefault();
}, [setHeld, startTalking]); if (isHeld) stopTalking();
setHeld(false);
},
[isHeld, setHeld, stopTalking]
);
const onButtonMouseDown = useCallback(
(e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
setHeld(true);
startTalking();
},
[setHeld, startTalking]
);
const onButtonTouchStart = useCallback(
(e: React.TouchEvent<HTMLButtonElement>) => {
e.preventDefault();
setHeld(true);
startTalking();
},
[setHeld, startTalking]
);
useEffect(() => { useEffect(() => {
window.addEventListener("mouseup", onDocumentMouseUp); window.addEventListener("mouseup", onWindowMouseUp);
window.addEventListener("touchend", onWindowTouchEnd);
return () => { return () => {
window.removeEventListener("mouseup", onDocumentMouseUp); window.removeEventListener("mouseup", onWindowMouseUp);
window.removeEventListener("touchend", onWindowTouchEnd);
}; };
}, [onDocumentMouseUp]); }, [onWindowMouseUp, onWindowTouchEnd]);
return ( return (
<button <button
className={classNames(styles.pttButton, { className={classNames(styles.pttButton, {
@ -67,6 +94,7 @@ export const PTTButton: React.FC<Props> = ({
[styles.error]: showTalkOverError, [styles.error]: showTalkOverError,
})} })}
onMouseDown={onButtonMouseDown} onMouseDown={onButtonMouseDown}
onTouchStart={onButtonTouchStart}
> >
{activeSpeakerIsLocalUser || !activeSpeakerUserId ? ( {activeSpeakerIsLocalUser || !activeSpeakerUserId ? (
<MicIcon <MicIcon

View file

@ -10,6 +10,12 @@
width: 100%; width: 100%;
} }
@media (hover: none) {
.pttCallView {
user-select: none;
}
}
.center { .center {
width: 100%; width: 100%;
display: flex; display: flex;

View file

@ -38,6 +38,43 @@ import { ReactComponent as AudioIcon } from "../icons/Audio.svg";
import { usePTTSounds } from "../sound/usePttSounds"; import { usePTTSounds } from "../sound/usePttSounds";
import { PTTClips } from "../sound/PTTClips"; import { PTTClips } from "../sound/PTTClips";
function getPromptText(
showTalkOverError: boolean,
pttButtonHeld: boolean,
activeSpeakerIsLocalUser: boolean,
talkOverEnabled: boolean,
activeSpeakerUserId: string,
activeSpeakerDisplayName: string
): string {
const isTouchScreen = Boolean(window.ontouchstart !== undefined);
if (showTalkOverError) {
return "You can't talk at the same time";
}
if (pttButtonHeld && activeSpeakerIsLocalUser) {
if (isTouchScreen) {
return "Release to stop";
} else {
return "Release spacebar key to stop";
}
}
if (talkOverEnabled && activeSpeakerUserId && !activeSpeakerIsLocalUser) {
if (isTouchScreen) {
return `Press and hold to talk over ${activeSpeakerDisplayName}`;
} else {
return `Press and hold spacebar to talk over ${activeSpeakerDisplayName}`;
}
}
if (isTouchScreen) {
return "Press and hold to talk";
} else {
return "Press and hold spacebar to talk";
}
}
interface Props { interface Props {
client: MatrixClient; client: MatrixClient;
roomId: string; roomId: string;
@ -163,15 +200,14 @@ export const PTTCallView: React.FC<Props> = ({
stopTalking={stopTalking} stopTalking={stopTalking}
/> />
<p className={styles.actionTip}> <p className={styles.actionTip}>
{showTalkOverError {getPromptText(
? "You can't talk at the same time" showTalkOverError,
: pttButtonHeld && activeSpeakerIsLocalUser pttButtonHeld,
? "Release spacebar key to stop" activeSpeakerIsLocalUser,
: talkOverEnabled && talkOverEnabled,
activeSpeakerUserId && activeSpeakerUserId,
!activeSpeakerIsLocalUser activeSpeakerDisplayName
? `Press and hold spacebar to talk over ${activeSpeakerDisplayName}` )}
: "Press and hold spacebar to talk"}
</p> </p>
{userMediaFeeds.map((callFeed) => ( {userMediaFeeds.map((callFeed) => (
<PTTFeed <PTTFeed