Skip to content

Commit

Permalink
Merge pull request #6508 from DougReeder/web-share-api
Browse files Browse the repository at this point in the history
Invites & sharing Room URL use Web Share API if available
  • Loading branch information
Exairnous authored Oct 29, 2024
2 parents 33ed11f + 730a9d2 commit 95a08fc
Show file tree
Hide file tree
Showing 14 changed files with 193 additions and 16 deletions.
7 changes: 6 additions & 1 deletion src/assets/locales/ca.json
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,11 @@
"invite-link-input-field.revoke-confirm-yes": "Si",
"invite-popover.embed-code": "Incrusta el codi",
"invite-popover.room-link": "Enllaç a la sala",
"invite-popover.share-in-english": "Share in English",
"invite-popover.share-invitation": "Share Invitation",
"invite-popover.share-room-link": "Share Room Link",
"invite-popover.what-this-is": "{appName} is an immersive 3D space you can access on any device.",
"invite-popover.share-title": "You're invited to join room “{roomName}” on {appName}",
"invite-popover.title": "Convida",
"invite-tooltip.description": "Copia l'enllaç de la sala per convidar els altres a la sala",
"leave-room-modal.create-room.confirm": "Surt i crea una sala",
Expand Down Expand Up @@ -700,4 +705,4 @@
"webvr-unsupported-modal.title": "Entrar en VR",
"webvr-unsupported-modal.webvr-rocks-link": "For a list of browsers with experimental VR support, visit <a>WebVR Rocks</a>.",
"whats-new-page.title": "Què hi ha de nou"
}
}
5 changes: 5 additions & 0 deletions src/assets/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@
"invite-link-input-field.revoke-confirm-yes": "Ja",
"invite-popover.embed-code": "Raum einbetten",
"invite-popover.room-link": "Raumlink",
"invite-popover.share-in-english": "Auf Englisch teilen",
"invite-popover.share-invitation": "Einladung teilen",
"invite-popover.share-room-link": "Raumlink teilen",
"invite-popover.what-this-is": "{appName} ist eine immersiver 3D-Welt, die Sie von jedem Gerät aus verwenden können.",
"invite-popover.share-title": "Sie wurden eingeladen, dem Raum „{roomName}” in {appName} beizutreten.",
"invite-popover.title": "Einladen",
"leave-room-modal.create-room.confirm": "Verlassen und Raum erstellen",
"leave-room-modal.create-room.message": "Beim Anlegen eines neuen Raums wird dieser verlassen. Bist du sicher?",
Expand Down
5 changes: 5 additions & 0 deletions src/assets/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,11 @@
"invite-link-input-field.revoke-confirm-yes": "oui",
"invite-popover.embed-code": "Intégrer le code",
"invite-popover.room-link": "Lien vers la Salle",
"invite-popover.share-in-english": "Share in English",
"invite-popover.share-invitation": "Share Invitation",
"invite-popover.share-room-link": "Share Room Link",
"invite-popover.what-this-is": "{appName} is an immersive 3D space you can access on any device.",
"invite-popover.share-title": "You're invited to join room “{roomName}” on {appName}",
"invite-popover.title": "Inviter",
"leave-room-modal.create-room.confirm": "Partir et créer une nouvelle salle",
"leave-room-modal.create-room.message": "Créer une nouvelle salle vous fera quitter celle-ci. Confirmer ?",
Expand Down
5 changes: 5 additions & 0 deletions src/assets/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,11 @@
"invite-popover.embed-code": "Embed Code",
"invite-popover.room-code": "Codice Stanza",
"invite-popover.room-link": "Link Stanza",
"invite-popover.share-in-english": "Share in English",
"invite-popover.share-invitation": "Share Invitation",
"invite-popover.share-room-link": "Share Room Link",
"invite-popover.what-this-is": "{appName} is an immersive 3D space you can access on any device.",
"invite-popover.share-title": "You're invited to join room “{roomName}” on {appName}",
"invite-popover.title": "Invita",
"leave-room-modal.create-room.confirm": "Esci e crea una stanza",
"leave-room-modal.create-room.message": "Creando una stanza uscirai da questa. Sei sicuro?",
Expand Down
5 changes: 5 additions & 0 deletions src/assets/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,11 @@
"invite-link-input-field.revoke-confirm-yes": "はい",
"invite-popover.embed-code": "埋め込みコード",
"invite-popover.room-link": "ルームリンク",
"invite-popover.share-in-english": "Share in English",
"invite-popover.share-invitation": "Share Invitation",
"invite-popover.share-room-link": "Share Room Link",
"invite-popover.what-this-is": "{appName} is an immersive 3D space you can access on any device.",
"invite-popover.share-title": "You're invited to join room “{roomName}” on {appName}",
"invite-popover.title": "招待",
"leave-room-modal.create-room.confirm": "退室および新規ルーム生成",
"leave-room-modal.create-room.message": "新しいルームを作成し、このルームが残ります。よろしいですか?",
Expand Down
5 changes: 5 additions & 0 deletions src/assets/locales/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,11 @@
"preferences-screen.prompt-for-refresh": "환경설정이 저장되지만, 페이지를 새로 고칠 때까지 일부 변경사항이 적용되지 않습니다.",
"preferences-screen.refresh-now": "새로고침하기",
"invite-popover.room-link": "Room Link",
"invite-popover.share-in-english": "Share in English",
"invite-popover.share-invitation": "Share Invitation",
"invite-popover.share-room-link": "Share Room Link",
"invite-popover.what-this-is": "{appName} is an immersive 3D space you can access on any device.",
"invite-popover.share-title": "You're invited to join room “{roomName}” on {appName}",
"invite-popover.embed-code": "Embed Code",
"user-profile-sidebar.promote-button": "관리자로 임명하기",
"user-profile-sidebar.demote-button": "참가자로 변경하기",
Expand Down
5 changes: 5 additions & 0 deletions src/assets/locales/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@
"invite-link-input-field.revoke-confirm-yes": "sim",
"invite-popover.embed-code": "Código Embedded",
"invite-popover.room-link": "Link da Sala",
"invite-popover.share-in-english": "Share in English",
"invite-popover.share-invitation": "Share Invitation",
"invite-popover.share-room-link": "Share Room Link",
"invite-popover.what-this-is": "{appName} is an immersive 3D space you can access on any device.",
"invite-popover.share-title": "You're invited to join room “{roomName}” on {appName}",
"invite-popover.title": "Convidar",
"leave-room-modal.create-room.confirm": "Sair da Sala",
"leave-room-modal.create-room.message": "Se você criar uma nova sala, você sairá da sala atual. Você tem certeza?",
Expand Down
7 changes: 6 additions & 1 deletion src/assets/locales/zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@
"invite-popover.enter-code": "输入代码在 {hubslink}",
"invite-popover.room-code": "房间密码",
"invite-popover.room-link": "房间链接",
"invite-popover.share-in-english": "Share in English",
"invite-popover.share-invitation": "Share Invitation",
"invite-popover.share-room-link": "Share Room Link",
"invite-popover.what-this-is": "{appName} is an immersive 3D space you can access on any device.",
"invite-popover.share-title": "You're invited to join room “{roomName}” on {appName}",
"invite-popover.title": "邀请",
"leave-room-modal.create-room.confirm": "离开并创造一个房间",
"leave-room-modal.create-room.message": "创造一个新房间你将会离开此房间. 你确定吗?",
Expand Down Expand Up @@ -659,4 +664,4 @@
"preferences-screen.prompt-for-refresh": "您的设置将被保存,但某些更改只有在刷新页面后才会生效。",
"preferences-screen.refresh-now": "现在更新",
"preferences-screen.preference.fx-aa-mode": "抗锯齿模式"
}
}
5 changes: 5 additions & 0 deletions src/assets/locales/zh-tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@
"invite-popover.enter-code": "輸入密碼在 {hubslink}",
"invite-popover.room-code": "房間密碼",
"invite-popover.room-link": "房間連結",
"invite-popover.share-in-english": "Share in English",
"invite-popover.share-invitation": "Share Invitation",
"invite-popover.share-room-link": "Share Room Link",
"invite-popover.what-this-is": "{appName} is an immersive 3D space you can access on any device.",
"invite-popover.share-title": "You're invited to join room “{roomName}” on {appName}",
"invite-popover.title": "邀請",
"leave-room-modal.create-room.confirm": "離開並創造一個房間",
"leave-room-modal.create-room.message": "創造一個新房間你將會離開此房間. 你確定嗎?",
Expand Down
58 changes: 54 additions & 4 deletions src/react-components/room/InvitePopover.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useState } from "react";
import PropTypes from "prop-types";
import styles from "./InvitePopover.scss";
import { CopyableTextInputField } from "../input/CopyableTextInputField";
Expand All @@ -8,23 +8,71 @@ import { ReactComponent as InviteIcon } from "../icons/Invite.svg";
import { Column } from "../layout/Column";
import { InviteLinkInputField } from "./InviteLinkInputField";
import { FormattedMessage, defineMessage, useIntl } from "react-intl";
import { ToolTip } from "@mozilla/lilypad-ui";
import { Checkbox, ToolTip } from "@mozilla/lilypad-ui";
import { Button } from "../input/Button";
import isMobile from "../../utils/is-mobile";
import { canShare } from "../../utils/share";
import { ReactComponent as ShareIcon } from "../icons/Share.svg";

function InvitePopoverContent({ url, embed, inviteRequired, fetchingInvite, inviteUrl, revokeInvite }) {
function InvitePopoverContent({
url,
embed,
inviteRequired,
fetchingInvite,
inviteUrl,
revokeInvite,
shareUrlHandler
}) {
const [isShareInEnglish, setIsShareInEnglish] = useState(false);
const intl = useIntl();
return (
<Column center padding grow gap="lg" className={styles.invitePopover}>
{inviteRequired ? (
<>
{canShare() && (
<>
<Button preset="primary" onClick={shareUrlHandler.bind(this, isShareInEnglish)}>
<ShareIcon />
<span>
<FormattedMessage id="invite-popover.share-invitation" defaultMessage="Share Invitation" />
</span>
</Button>
{!intl?.locale?.startsWith?.("en") && (
<Checkbox
label={<FormattedMessage id="invite-popover.share-in-english" defaultMessage="Share in English" />}
checked={isShareInEnglish}
onChange={() => setIsShareInEnglish(inEnglish => !inEnglish)}
/>
)}
</>
)}
<InviteLinkInputField fetchingInvite={fetchingInvite} inviteUrl={inviteUrl} onRevokeInvite={revokeInvite} />
</>
) : (
<>
{canShare() && (
<>
<Button preset="primary" onClick={shareUrlHandler.bind(this, isShareInEnglish)}>
<ShareIcon />
<span>
<FormattedMessage id="invite-popover.share-room-link" defaultMessage="Share Room Link" />
</span>
</Button>
{!intl?.locale?.startsWith?.("en") && (
<Checkbox
label={<FormattedMessage id="invite-popover.share-in-english" defaultMessage="Share in English" />}
checked={isShareInEnglish}
onChange={() => setIsShareInEnglish(inEnglish => !inEnglish)}
/>
)}
</>
)}
<CopyableTextInputField
label={<FormattedMessage id="invite-popover.room-link" defaultMessage="Room Link" />}
value={url}
buttonPreset="accent3"
/>
{embed && (
{!isMobile() && embed && (
<CopyableTextInputField
label={<FormattedMessage id="invite-popover.embed-code" defaultMessage="Embed Code" />}
value={embed}
Expand Down Expand Up @@ -65,6 +113,7 @@ export function InvitePopoverButton({
fetchingInvite,
inviteUrl,
revokeInvite,
shareUrlHandler,
...rest
}) {
const intl = useIntl();
Expand All @@ -82,6 +131,7 @@ export function InvitePopoverButton({
fetchingInvite={fetchingInvite}
inviteUrl={inviteUrl}
revokeInvite={revokeInvite}
shareUrlHandler={shareUrlHandler}
/>
)}
placement="top-start"
Expand Down
13 changes: 11 additions & 2 deletions src/react-components/room/InvitePopoverContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ import { hubUrl } from "../../utils/phoenix-utils";
import { InvitePopoverButton } from "./InvitePopover";
import { handleExitTo2DInterstitial } from "../../utils/vr-interstitial";
import { useInviteUrl } from "./hooks/useInviteUrl";
import { useIntl } from "react-intl";
import { shareInviteUrl } from "../../utils/share";

export function InvitePopoverContainer({ hub, hubChannel, scene, store, ...rest }) {
const intl = useIntl();

// TODO: Move to Hub class
const shortUrl = `https://${configs.SHORTLINK_DOMAIN}`;
const url = `${shortUrl}/${hub.hub_id}`;
const url = hubUrl(hub.hub_id, {}).href;
// const shortUrl = `https://${configs.SHORTLINK_DOMAIN}`;
// const url = `${shortUrl}/${hub.hub_id}`;

let embedText = null;
const embedToken = hub.embed_token || store.getEmbedTokenForHub(hub);
Expand Down Expand Up @@ -53,6 +58,10 @@ export function InvitePopoverContainer({ hub, hubChannel, scene, store, ...rest
fetchingInvite={fetchingInvite}
inviteUrl={inviteUrl}
revokeInvite={revokeInvite}
shareUrlHandler={shareInviteUrl.bind(this, intl, inviteRequired ? inviteUrl : url, {
roomName: hub.name,
appName: configs.translation("app-name")
})}
url={url}
embed={embedText}
popoverApiRef={popoverApiRef}
Expand Down
44 changes: 41 additions & 3 deletions src/react-components/room/RoomSettingsSidebar.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { useEffect } from "react";
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import { useForm } from "react-hook-form";
import styles from "./RoomSettingsSidebar.scss";
import { Sidebar } from "../sidebar/Sidebar";
import { CloseButton } from "../input/CloseButton";
import { InputField } from "../input/InputField";
import { FormattedMessage, useIntl } from "react-intl";
import { ApplyButton } from "../input/Button";
import { ApplyButton, Button } from "../input/Button";
import { TextInputField } from "../input/TextInputField";
import { TextAreaInputField } from "../input/TextAreaInputField";
import { ToggleInput } from "../input/ToggleInput";
Expand All @@ -16,6 +16,10 @@ import { BackButton } from "../input/BackButton";
import { SceneInfo } from "./RoomSidebar";
import { Column } from "../layout/Column";
import { InviteLinkInputField } from "./InviteLinkInputField";
import { canShare, shareInviteUrl } from "../../utils/share";
import { ReactComponent as ShareIcon } from "../icons/Share.svg";
import { Checkbox } from "@mozilla/lilypad-ui";
import configs from "../../utils/configs";

export function RoomSettingsSidebar({
showBackButton,
Expand Down Expand Up @@ -52,6 +56,8 @@ export function RoomSettingsSidebar({
}
}, [spawnAndMoveMedia, setValue]);

const [isShareInEnglish, setIsShareInEnglish] = useState(false);

return (
<Sidebar
title={<FormattedMessage id="room-settings-sidebar.title" defaultMessage="Room Settings" />}
Expand Down Expand Up @@ -134,7 +140,39 @@ export function RoomSettingsSidebar({
/>
</RadioInputField>
{entryMode === "invite" && (
<InviteLinkInputField fetchingInvite={fetchingInvite} inviteUrl={inviteUrl} onRevokeInvite={onRevokeInvite} />
<>
{canShare() && (
<>
<Button
preset="primary"
onClick={shareInviteUrl.bind(
this,
intl,
inviteUrl,
{ roomName: room.name, appName: configs.translation("app-name") },
isShareInEnglish
)}
>
<ShareIcon />
<span>
<FormattedMessage id="invite-popover.share-invitation" defaultMessage="Share Invitation" />
</span>
</Button>
{!intl?.locale?.startsWith?.("en") && (
<Checkbox
label={<FormattedMessage id="invite-popover.share-in-english" defaultMessage="Share in English" />}
checked={isShareInEnglish}
onChange={() => setIsShareInEnglish(inEnglish => !inEnglish)}
/>
)}
</>
)}
<InviteLinkInputField
fetchingInvite={fetchingInvite}
inviteUrl={inviteUrl}
onRevokeInvite={onRevokeInvite}
/>
</>
)}
{showPublicRoomSetting && (
<ToggleInput
Expand Down
5 changes: 3 additions & 2 deletions src/utils/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { AVAILABLE_LOCALES, FALLBACK_LOCALES } from "../assets/locales/locale_co

// These are set in the admin panel and are only included as fallbacks.
const defaultLocaleData = {
"app-name": "App",
"app-name": location.hostname,
"editor-name": "Scene Editor",
"contact-email": "[email protected]",
"company-name": "Company",
"share-hashtag": "#app",
"app-description": "Gather share and collaborate together in a virtual, private and safe space",
// what you can do here
"app-description": "Gather, share, and collaborate together in a virtual, private, and safe space.",
"app-tagline": "Private social VR in your web browser"
};

Expand Down
40 changes: 37 additions & 3 deletions src/utils/share.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const isMobileVR = AFRAME.utils.device.isMobileVR();
import configs from "./configs";
import { createIntl, createIntlCache } from "react-intl";

export function canShare() {
// TODO, fix up when OB/FxR support sharing
return navigator.share && !isMobileVR;
return "function" === typeof navigator.share;
}

/**
Expand All @@ -25,3 +25,37 @@ export function share(opts) {
return Promise.resolve();
}
}

export async function shareInviteUrl(intl, url, values = {}, inEnglish = false, event) {
try {
event.preventDefault();
event.stopPropagation();
if (inEnglish) {
const cache = createIntlCache(); // prevents memory leak
intl = createIntl({ locale: "en", messages: {} }, cache);
}
const title = intl.formatMessage(
{
id: "invite-popover.share-title",
defaultMessage: "You're invited to join room “{roomName}” on {appName}"
},
values
);
// What this is + what you can do here
const text =
intl.formatMessage(
{
id: "invite-popover.what-this-is",
defaultMessage: "{appName} is an immersive 3D space you can access on any device."
},
values
) +
" " +
configs.translation("app-description");
const data = { title, text, url };
console.info(`attempting to share:`, data);
await share(data);
} catch (error) {
console.error("unable to share:", error);
}
}

0 comments on commit 95a08fc

Please sign in to comment.