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:
		
				commit
				
					
						9fbe4278c2
					
				
			
		
					 3 changed files with 90 additions and 20 deletions
				
			
		| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue