diff --git a/res/css/views/dialogs/_ShareDialog.pcss b/res/css/views/dialogs/_ShareDialog.pcss index 086222af31b..800dee60100 100644 --- a/res/css/views/dialogs/_ShareDialog.pcss +++ b/res/css/views/dialogs/_ShareDialog.pcss @@ -13,7 +13,7 @@ Please see LICENSE files in the repository root for full details. .mx_ShareDialog .mx_ShareDialog_content { margin: 10px 0; - + text-align: center; .mx_CopyableText { width: unset; /* full width */ @@ -27,27 +27,51 @@ Please see LICENSE files in the repository root for full details. } } -.mx_ShareDialog_split { +.mx_ShareDialog_url { + text-align: center; + color: var(--cpd-color-text-secondary); + overflow-wrap: break-word; + max-width: 400px; +} +.mx_ShareDialog_checkbox { + display: inline-block; + margin: var(--cpd-space-4x) 0; +} +.mx_ShareDialog_button { + width: 100%; +} + +.mx_ShareDialog_qrCode { + display: flex; + justify-content: center; +} + +.mx_ShareDialog_qrCode img { + margin: 0 var(--cpd-space-8x); + image-rendering: pixelated; +} + +.mx_LegacyShareDialog_split { display: flex; flex-wrap: wrap; } -.mx_ShareDialog_qrcode_container { +.mx_LegacyShareDialog_qrcode_container { float: left; height: 256px; width: 256px; margin-right: 64px; } -.mx_ShareDialog_qrcode_container + .mx_ShareDialog_social_container { +.mx_LegacyShareDialog_qrcode_container + .mx_LegacyShareDialog_social_container { width: 299px; } -.mx_ShareDialog_social_container { +.mx_LegacyShareDialog_social_container { display: inline-block; } -.mx_ShareDialog_social_icon { +.mx_LegacyShareDialog_social_icon { display: inline-grid; margin-right: 10px; margin-bottom: 10px; diff --git a/src/components/views/dialogs/ShareDialog.tsx b/src/components/views/dialogs/ShareDialog.tsx index f9382227e4e..0a2dbaf9e19 100644 --- a/src/components/views/dialogs/ShareDialog.tsx +++ b/src/components/views/dialogs/ShareDialog.tsx @@ -9,51 +9,20 @@ Please see LICENSE files in the repository root for full details. import * as React from "react"; import { Room, RoomMember, MatrixEvent, User } from "matrix-js-sdk/src/matrix"; +import { Button, Text } from "@vector-im/compound-web"; +import LinkIcon from "@vector-im/compound-design-tokens/assets/web/icons/link"; import { _t } from "../../../languageHandler"; import QRCode from "../elements/QRCode"; import { RoomPermalinkCreator, makeUserPermalink } from "../../../utils/permalinks/Permalinks"; -import { selectText } from "../../../utils/strings"; +import { copyPlaintext, selectText } from "../../../utils/strings"; import StyledCheckbox from "../elements/StyledCheckbox"; import SettingsStore from "../../../settings/SettingsStore"; import { UIFeature } from "../../../settings/UIFeature"; import BaseDialog from "./BaseDialog"; -import CopyableText from "../elements/CopyableText"; import { XOR } from "../../../@types/common"; - -/* eslint-disable @typescript-eslint/no-require-imports */ -const socials = [ - { - name: "Facebook", - img: require("../../../../res/img/social/facebook.png"), - url: (url: string) => `https://www.facebook.com/sharer/sharer.php?u=${url}`, - }, - { - name: "Twitter", - img: require("../../../../res/img/social/twitter-2.png"), - url: (url: string) => `https://twitter.com/home?status=${url}`, - }, - /* // icon missing - name: 'Google Plus', - img: 'img/social/', - url: (url) => `https://plus.google.com/share?url=${url}`, - },*/ { - name: "LinkedIn", - img: require("../../../../res/img/social/linkedin.png"), - url: (url: string) => `https://www.linkedin.com/shareArticle?mini=true&url=${url}`, - }, - { - name: "Reddit", - img: require("../../../../res/img/social/reddit.png"), - url: (url: string) => `https://www.reddit.com/submit?url=${url}`, - }, - { - name: "email", - img: require("../../../../res/img/social/email-1.png"), - url: (url: string) => `mailto:?body=${url}`, - }, -]; -/* eslint-enable @typescript-eslint/no-require-imports */ +import { ButtonEvent } from "../elements/AccessibleButton"; +import CopyableText from "../elements/CopyableText"; interface BaseProps { /** @@ -91,7 +60,168 @@ interface IState { permalinkCreator: RoomPermalinkCreator | null; } -export default class ShareDialog extends React.PureComponent, IState> { +// TODO: make this a Rect.FC +export class ShareDialog extends React.PureComponent, IState> { + public constructor(props: XOR) { + super(props); + + let permalinkCreator: RoomPermalinkCreator | null = null; + if (props.target instanceof Room) { + permalinkCreator = new RoomPermalinkCreator(props.target); + permalinkCreator.load(); + } + + this.state = { + // MatrixEvent defaults to share linkSpecificEvent + linkSpecificEvent: this.props.target instanceof MatrixEvent, + permalinkCreator, + }; + } + + public static onLinkClick(e: React.MouseEvent): void { + e.preventDefault(); + selectText(e.currentTarget); + } + + private onLinkSpecificEventCheckboxClick = (): void => { + this.setState({ + linkSpecificEvent: !this.state.linkSpecificEvent, + }); + }; + + private getUrl(): string { + if (this.props.target instanceof URL) { + return this.props.target.toString(); + } else if (this.props.target instanceof Room) { + if (this.state.linkSpecificEvent) { + const events = this.props.target.getLiveTimeline().getEvents(); + return this.state.permalinkCreator!.forEvent(events[events.length - 1].getId()!); + } else { + return this.state.permalinkCreator!.forShareableRoom(); + } + } else if (this.props.target instanceof User || this.props.target instanceof RoomMember) { + return makeUserPermalink(this.props.target.userId); + } else if (this.state.linkSpecificEvent) { + return this.props.permalinkCreator!.forEvent(this.props.target.getId()!); + } else { + return this.props.permalinkCreator!.forShareableRoom(); + } + } + + public render(): React.ReactNode { + let title: string | undefined; + let checkbox: JSX.Element | undefined; + + if (this.props.target instanceof URL) { + title = this.props.customTitle ?? _t("share|title_link"); + } else if (this.props.target instanceof Room) { + title = this.props.customTitle ?? _t("share|title_room"); + + const events = this.props.target.getLiveTimeline().getEvents(); + if (events.length > 0) { + checkbox = ( +
+ + {_t("share|permalink_most_recent")} + +
+ ); + } + } else if (this.props.target instanceof User || this.props.target instanceof RoomMember) { + title = this.props.customTitle ?? _t("share|title_user"); + } else if (this.props.target instanceof MatrixEvent) { + title = this.props.customTitle ?? _t("share|title_message"); + checkbox = ( +
+ + {_t("share|permalink_message")} + +
+ ); + } + + const matrixToUrl = this.getUrl(); + + const showQrCode = SettingsStore.getValue(UIFeature.ShareQRCode); + const onButtonClick = async (e: ButtonEvent): Promise => { + e.preventDefault(); + + await copyPlaintext(matrixToUrl); + this.props.onFinished(); + }; + + return ( + + {this.props.subtitle &&

{this.props.subtitle}

} +
+ {showQrCode && } + + {matrixToUrl} + + {checkbox} + +
+
+ ); + } +} + +// LEGACY SHARE DIALOG + +/* eslint-disable @typescript-eslint/no-require-imports */ +const socials = [ + { + name: "Facebook", + img: require("../../../../res/img/social/facebook.png"), + url: (url: string) => `https://www.facebook.com/sharer/sharer.php?u=${url}`, + }, + { + name: "Twitter", + img: require("../../../../res/img/social/twitter-2.png"), + url: (url: string) => `https://twitter.com/home?status=${url}`, + }, + /* // icon missing + name: 'Google Plus', + img: 'img/social/', + url: (url) => `https://plus.google.com/share?url=${url}`, + },*/ { + name: "LinkedIn", + img: require("../../../../res/img/social/linkedin.png"), + url: (url: string) => `https://www.linkedin.com/shareArticle?mini=true&url=${url}`, + }, + { + name: "Reddit", + img: require("../../../../res/img/social/reddit.png"), + url: (url: string) => `https://www.reddit.com/submit?url=${url}`, + }, + { + name: "email", + img: require("../../../../res/img/social/email-1.png"), + url: (url: string) => `mailto:?body=${url}`, + }, +]; +/* eslint-enable @typescript-eslint/no-require-imports */ + +export default class LegacyShareDialog extends React.PureComponent, IState> { public constructor(props: XOR) { super(props); @@ -187,14 +317,14 @@ export default class ShareDialog extends React.PureComponent
-
+
{showQrCode && ( -
+
)} {showSocials && ( -
+
{socials.map((social) => ( {social.name} diff --git a/src/components/views/rooms/RoomHeader/CallGuestLinkButton.tsx b/src/components/views/rooms/RoomHeader/CallGuestLinkButton.tsx index ae8e7be16bf..8c000bdf3bc 100644 --- a/src/components/views/rooms/RoomHeader/CallGuestLinkButton.tsx +++ b/src/components/views/rooms/RoomHeader/CallGuestLinkButton.tsx @@ -12,7 +12,7 @@ import { logger } from "matrix-js-sdk/src/logger"; import { EventType, JoinRule, Room } from "matrix-js-sdk/src/matrix"; import Modal from "../../../../Modal"; -import ShareDialog from "../../dialogs/ShareDialog"; +import { ShareDialog } from "../../dialogs/ShareDialog"; import { _t } from "../../../../languageHandler"; import SettingsStore from "../../../../settings/SettingsStore"; import { calculateRoomVia } from "../../../../utils/permalinks/Permalinks"; diff --git a/test/unit-tests/components/views/dialogs/ShareDialog-test.tsx b/test/unit-tests/components/views/dialogs/ShareDialog-test.tsx index cb7d556235c..232423630e7 100644 --- a/test/unit-tests/components/views/dialogs/ShareDialog-test.tsx +++ b/test/unit-tests/components/views/dialogs/ShareDialog-test.tsx @@ -75,7 +75,7 @@ describe("ShareDialog", () => { return originalGetValue(feature); }); const { container } = render(, getWrapper()); - const qrCodesVisible = container.getElementsByClassName("mx_ShareDialog_qrcode_container").length > 0; + const qrCodesVisible = container.getElementsByClassName("mx_LegacyShareDialog_qrcode_container").length > 0; expect(qrCodesVisible).toBe(true); }); @@ -86,7 +86,7 @@ describe("ShareDialog", () => { return originalGetValue(feature); }); const { container } = render(, getWrapper()); - const qrCodesVisible = container.getElementsByClassName("mx_ShareDialog_social_container").length > 0; + const qrCodesVisible = container.getElementsByClassName("mx_LegacyShareDialog_social_container").length > 0; expect(qrCodesVisible).toBe(true); }); it("renders custom title and subtitle", () => {