diff --git a/src/assets/share_message.png b/src/assets/share_message.png new file mode 100644 index 0000000000..6fcc189753 Binary files /dev/null and b/src/assets/share_message.png differ diff --git a/src/assets/spawn_message-hover.png b/src/assets/spawn_message-hover.png deleted file mode 100644 index ce99dd993b..0000000000 Binary files a/src/assets/spawn_message-hover.png and /dev/null differ diff --git a/src/assets/stylesheets/presence-log.scss b/src/assets/stylesheets/presence-log.scss index 3b0b302103..c8ee0d644c 100644 --- a/src/assets/stylesheets/presence-log.scss +++ b/src/assets/stylesheets/presence-log.scss @@ -64,27 +64,38 @@ max-width: 75%; } - :local(.spawn-message) { + :local(.icon-button) { appearance: none; -moz-appearance: none; -webkit-appearance: none; outline-style: none; width: 24px; height: 24px; - background-size: 100%; + background-size: 20px; + background-position: center; + background-repeat: no-repeat; border: 0; display: flex; justify-content: center; align-items: center; align-self: flex-start; cursor: pointer; - background-image: url(../spawn_message.png); margin-right: 6px; + border-radius: 12px; background-color: transparent; + + &:hover { + background-color: $action-color; + } + } + + :local(.spawn-message) { + background-image: url(../spawn_message.png); } - :local(.spawn-message):hover { - background-image: url(../spawn_message-hover.png); + // TODO replace these icons with share button + :local(.share) { + background-image: url(../share_message.png); } &:local(.media) { @@ -99,7 +110,7 @@ img { height: 35px; - margin-right: 8px; + margin-left: 8px; border: 2px solid rgba(255,255,255,0.15); display: block; border-radius: 5px; diff --git a/src/react-components/invite-dialog.js b/src/react-components/invite-dialog.js index 414194081d..62fe7975b1 100644 --- a/src/react-components/invite-dialog.js +++ b/src/react-components/invite-dialog.js @@ -3,6 +3,7 @@ import PropTypes from "prop-types"; import copy from "copy-to-clipboard"; import classNames from "classnames"; import { FormattedMessage } from "react-intl"; +import { share } from "../utils/share"; import styles from "../assets/stylesheets/invite-dialog.scss"; @@ -25,11 +26,11 @@ export default class InviteDialog extends Component { shareButtonActive: false }; - shareClicked = link => { + shareClicked = url => { this.setState({ shareButtonActive: true }); - setTimeout(() => this.setState({ shareButtonActive: false }), 5000); - - navigator.share({ title: "Join me now in #hubs!", url: link }); + share({ url, title: "Join me now in #hubs!" }).then(() => { + this.setState({ shareButtonActive: false }); + }); }; copyClicked = link => { @@ -46,11 +47,6 @@ export default class InviteDialog extends Component { const shortLinkText = `hub.link/${this.props.hubId}`; const shortLink = "https://" + shortLinkText; - const tweetText = `Join me now in #hubs!`; - const tweetLink = `https://twitter.com/share?url=${encodeURIComponent(shortLink)}&text=${encodeURIComponent( - tweetText - )}`; - return (
@@ -89,9 +85,9 @@ export default class InviteDialog extends Component { )} {this.props.allowShare && !navigator.share && ( - + )}
diff --git a/src/react-components/photo-message.js b/src/react-components/photo-message.js new file mode 100644 index 0000000000..ac4cfbceb0 --- /dev/null +++ b/src/react-components/photo-message.js @@ -0,0 +1,44 @@ +import React from "react"; +import PropTypes from "prop-types"; + +import styles from "../assets/stylesheets/presence-log.scss"; +import classNames from "classnames"; + +import { share } from "../utils/share"; +import { getLandingPageForPhoto } from "../utils/phoenix-utils"; + +export default function PhotoMessage({ name, body: { src: url }, className, maySpawn, hubId }) { + const landingPageUrl = getLandingPageForPhoto(url); + const onShareClicked = share.bind(null, { + url: landingPageUrl, + title: `Taken in #hubs, join me at https://hub.link/${hubId}` + }); + return ( +
+ {maySpawn &&
+ ); +} +PhotoMessage.propTypes = { + name: PropTypes.string, + maySpawn: PropTypes.bool, + body: PropTypes.object, + className: PropTypes.string, + hubId: PropTypes.string +}; diff --git a/src/react-components/presence-log.js b/src/react-components/presence-log.js index 491b98aa03..4426ac46e1 100644 --- a/src/react-components/presence-log.js +++ b/src/react-components/presence-log.js @@ -3,12 +3,15 @@ import PropTypes from "prop-types"; import styles from "../assets/stylesheets/presence-log.scss"; import classNames from "classnames"; import { FormattedMessage } from "react-intl"; + import ChatMessage from "./chat-message"; +import PhotoMessage from "./photo-message"; export default class PresenceLog extends Component { static propTypes = { entries: PropTypes.array, - inRoom: PropTypes.bool + inRoom: PropTypes.bool, + hubId: PropTypes.string }; constructor(props) { @@ -54,26 +57,15 @@ export default class PresenceLog extends Component { /> ); case "spawn": { - const { src } = e.body; return ( -
- - - -
- - {e.name} - - - {"took a "} - - - photo - - . - -
-
+ ); } } diff --git a/src/react-components/ui-root.js b/src/react-components/ui-root.js index 7a3987d2bb..012afee70e 100644 --- a/src/react-components/ui-root.js +++ b/src/react-components/ui-root.js @@ -1027,12 +1027,14 @@ class UIRoot extends Component { {(!entryFinished || this.isWaitingForAutoExit()) && (
- +
{dialogContents}
)} - {entryFinished && } + {entryFinished && ( + + )} {entryFinished && (
diff --git a/src/scene-entry-manager.js b/src/scene-entry-manager.js index ed86791042..461f42107a 100644 --- a/src/scene-entry-manager.js +++ b/src/scene-entry-manager.js @@ -259,7 +259,6 @@ export default class SceneEntryManager { }); this.scene.addEventListener("photo_taken", e => { - console.log(e); this.hubChannel.sendMessage({ src: e.detail }, "spawn"); }); }; diff --git a/src/utils/phoenix-utils.js b/src/utils/phoenix-utils.js index 19619599af..5d5307db88 100644 --- a/src/utils/phoenix-utils.js +++ b/src/utils/phoenix-utils.js @@ -43,3 +43,8 @@ export function getReticulumFetchUrl(path) { return path; } } + +export function getLandingPageForPhoto(photoUrl) { + const parsedUrl = new URL(photoUrl); + return getReticulumFetchUrl(parsedUrl.pathname.replace(".png", ".html") + parsedUrl.search); +} diff --git a/src/utils/share.js b/src/utils/share.js new file mode 100644 index 0000000000..e563431ff0 --- /dev/null +++ b/src/utils/share.js @@ -0,0 +1,20 @@ +/** + * Wraps navigator.share with a fallback to twitter for unsupported browsers + */ +export function share(opts) { + if (navigator.share) { + return navigator.share(opts); + } else { + const { title, url } = opts; + const width = 550; + const height = 420; + const left = (screen.width - width) / 2; + const top = (screen.height - height) / 2; + const params = `scrollbars=no,menubar=no,toolbar=no,status=no,width=${width},height=${height},top=${top},left=${left}`; + const tweetLink = `https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent( + title + )}`; + window.open(tweetLink, "_blank", params); + return Promise.resolve(); + } +}