RoomDialog.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import React, { useState, useEffect, useRef } from "react";
  2. import { ToolButton } from "./ToolButton";
  3. import { t } from "../i18n";
  4. import useIsMobile from "../is-mobile";
  5. import { users, clipboard, start, stop } from "./icons";
  6. import "./RoomDialog.scss";
  7. import { copyTextToSystemClipboard } from "../clipboard";
  8. import { Dialog } from "./Dialog";
  9. import { AppState } from "../types";
  10. function RoomModal({
  11. activeRoomLink,
  12. onRoomCreate,
  13. onRoomDestroy,
  14. }: {
  15. activeRoomLink: string;
  16. onRoomCreate: () => void;
  17. onRoomDestroy: () => void;
  18. }) {
  19. const roomLinkInput = useRef<HTMLInputElement>(null);
  20. function copyRoomLink() {
  21. copyTextToSystemClipboard(activeRoomLink);
  22. if (roomLinkInput.current) {
  23. roomLinkInput.current.select();
  24. }
  25. }
  26. function selectInput(event: React.MouseEvent<HTMLInputElement>) {
  27. if (event.target !== document.activeElement) {
  28. event.preventDefault();
  29. (event.target as HTMLInputElement).select();
  30. }
  31. }
  32. return (
  33. <div className="RoomDialog-modal">
  34. {!activeRoomLink && (
  35. <>
  36. <p>{t("roomDialog.desc_intro")}</p>
  37. <p>{`🔒 ${t("roomDialog.desc_privacy")}`}</p>
  38. <p>{t("roomDialog.desc_start")}</p>
  39. <div className="RoomDialog-sessionStartButtonContainer">
  40. <ToolButton
  41. className="RoomDialog-startSession"
  42. type="button"
  43. icon={start}
  44. title={t("roomDialog.button_startSession")}
  45. aria-label={t("roomDialog.button_startSession")}
  46. showAriaLabel={true}
  47. onClick={onRoomCreate}
  48. />
  49. </div>
  50. </>
  51. )}
  52. {activeRoomLink && (
  53. <>
  54. <p>{t("roomDialog.desc_inProgressIntro")}</p>
  55. <p>{t("roomDialog.desc_shareLink")}</p>
  56. <div className="RoomDialog-linkContainer">
  57. <ToolButton
  58. type="button"
  59. icon={clipboard}
  60. title={t("labels.copy")}
  61. aria-label={t("labels.copy")}
  62. onClick={copyRoomLink}
  63. />
  64. <input
  65. value={activeRoomLink}
  66. readOnly={true}
  67. className="RoomDialog-link"
  68. ref={roomLinkInput}
  69. onPointerDown={selectInput}
  70. />
  71. </div>
  72. <p>{`🔒 ${t("roomDialog.desc_privacy")}`}</p>
  73. <p>
  74. <span role="img" aria-hidden="true">
  75. ⚠️
  76. </span>{" "}
  77. {t("roomDialog.desc_persistenceWarning")}
  78. </p>
  79. <p>{t("roomDialog.desc_exitSession")}</p>
  80. <div className="RoomDialog-sessionStartButtonContainer">
  81. <ToolButton
  82. className="RoomDialog-stopSession"
  83. type="button"
  84. icon={stop}
  85. title={t("roomDialog.button_stopSession")}
  86. aria-label={t("roomDialog.button_stopSession")}
  87. showAriaLabel={true}
  88. onClick={onRoomDestroy}
  89. />
  90. </div>
  91. </>
  92. )}
  93. </div>
  94. );
  95. }
  96. export function RoomDialog({
  97. isCollaborating,
  98. collaboratorCount,
  99. onRoomCreate,
  100. onRoomDestroy,
  101. }: {
  102. isCollaborating: AppState["isCollaborating"];
  103. collaboratorCount: number;
  104. onRoomCreate: () => void;
  105. onRoomDestroy: () => void;
  106. }) {
  107. const [modalIsShown, setModalIsShown] = useState(false);
  108. const [activeRoomLink, setActiveRoomLink] = useState("");
  109. const triggerButton = useRef<HTMLButtonElement>(null);
  110. const handleClose = React.useCallback(() => {
  111. setModalIsShown(false);
  112. triggerButton.current?.focus();
  113. }, []);
  114. useEffect(() => {
  115. setActiveRoomLink(isCollaborating ? window.location.href : "");
  116. }, [isCollaborating]);
  117. return (
  118. <>
  119. <ToolButton
  120. className={`RoomDialog-modalButton ${
  121. isCollaborating ? "is-collaborating" : ""
  122. }`}
  123. onClick={() => setModalIsShown(true)}
  124. icon={users}
  125. type="button"
  126. title={t("buttons.roomDialog")}
  127. aria-label={t("buttons.roomDialog")}
  128. showAriaLabel={useIsMobile()}
  129. ref={triggerButton}
  130. >
  131. {collaboratorCount > 0 && (
  132. <div className="RoomDialog-modalButton-collaborators">
  133. {collaboratorCount}
  134. </div>
  135. )}
  136. </ToolButton>
  137. {modalIsShown && (
  138. <Dialog
  139. maxWidth={800}
  140. onCloseRequest={handleClose}
  141. title={t("labels.createRoom")}
  142. >
  143. <RoomModal
  144. activeRoomLink={activeRoomLink}
  145. onRoomCreate={onRoomCreate}
  146. onRoomDestroy={onRoomDestroy}
  147. />
  148. </Dialog>
  149. )}
  150. </>
  151. );
  152. }