From 9e429ee6694aa9cdf7a51552d3851d046ce6e0bd Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Tue, 11 Aug 2020 14:26:12 +0100 Subject: [PATCH 1/4] Remove rebranding toast It's time to remove the rebranding toast, as we believe people have had sufficient warning now. Fixes https://github.com/vector-im/element-web/issues/14931 --- res/css/_components.scss | 1 - res/css/structures/_ToastContainer.scss | 4 - res/css/views/dialogs/_RebrandDialog.scss | 64 ------ res/img/element-logo.svg | 6 - res/img/riot-logo.svg | 6 - src/Lifecycle.js | 4 - src/RebrandListener.tsx | 184 ------------------ .../views/dialogs/RebrandDialog.tsx | 116 ----------- src/i18n/strings/en_EN.json | 9 - 9 files changed, 394 deletions(-) delete mode 100644 res/css/views/dialogs/_RebrandDialog.scss delete mode 100644 res/img/element-logo.svg delete mode 100644 res/img/riot-logo.svg delete mode 100644 src/RebrandListener.tsx delete mode 100644 src/components/views/dialogs/RebrandDialog.tsx diff --git a/res/css/_components.scss b/res/css/_components.scss index 0dc267e130..7dd8a2034d 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -72,7 +72,6 @@ @import "./views/dialogs/_KeyboardShortcutsDialog.scss"; @import "./views/dialogs/_MessageEditHistoryDialog.scss"; @import "./views/dialogs/_NewSessionReviewDialog.scss"; -@import "./views/dialogs/_RebrandDialog.scss"; @import "./views/dialogs/_RoomSettingsDialog.scss"; @import "./views/dialogs/_RoomSettingsDialogBridges.scss"; @import "./views/dialogs/_RoomUpgradeDialog.scss"; diff --git a/res/css/structures/_ToastContainer.scss b/res/css/structures/_ToastContainer.scss index e798e4ac52..544dcbc180 100644 --- a/res/css/structures/_ToastContainer.scss +++ b/res/css/structures/_ToastContainer.scss @@ -80,10 +80,6 @@ limitations under the License. } } - &.mx_Toast_icon_element_logo::after { - background-image: url("$(res)/img/element-logo.svg"); - } - .mx_Toast_title, .mx_Toast_body { grid-column: 2; } diff --git a/res/css/views/dialogs/_RebrandDialog.scss b/res/css/views/dialogs/_RebrandDialog.scss deleted file mode 100644 index 534584ae2a..0000000000 --- a/res/css/views/dialogs/_RebrandDialog.scss +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright 2020 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -.mx_RebrandDialog { - text-align: center; - - a:link, - a:hover, - a:visited { - @mixin mx_Dialog_link; - } - - .mx_Dialog_buttons { - margin-top: 43px; - text-align: center; - } -} - -.mx_RebrandDialog_body { - width: 550px; - margin-left: auto; - margin-right: auto; -} - -.mx_RebrandDialog_logoContainer { - margin-top: 35px; - margin-bottom: 20px; - display: flex; - align-items: center; - justify-content: center; -} - -.mx_RebrandDialog_logo { - margin-left: 28px; - margin-right: 28px; - width: 64px; - height: 64px; -} - -.mx_RebrandDialog_chevron::after { - content: ''; - display: inline-block; - width: 30px; - height: 30px; - mask-position: center; - mask-size: contain; - mask-repeat: no-repeat; - background-color: $muted-fg-color; - mask-image: url('$(res)/img/feather-customised/chevron-down.svg'); - transform: rotate(-90deg); -} diff --git a/res/img/element-logo.svg b/res/img/element-logo.svg deleted file mode 100644 index 2cd11ed193..0000000000 --- a/res/img/element-logo.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/res/img/riot-logo.svg b/res/img/riot-logo.svg deleted file mode 100644 index ac1e547234..0000000000 --- a/res/img/riot-logo.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/Lifecycle.js b/src/Lifecycle.js index 2bebe22f14..d2de31eb80 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -40,7 +40,6 @@ import ToastStore from "./stores/ToastStore"; import {IntegrationManagers} from "./integrations/IntegrationManagers"; import {Mjolnir} from "./mjolnir/Mjolnir"; import DeviceListener from "./DeviceListener"; -import RebrandListener from "./RebrandListener"; import {Jitsi} from "./widgets/Jitsi"; import {SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY} from "./BasePlatform"; @@ -647,8 +646,6 @@ async function startMatrixClient(startSyncing=true) { // Now that we have a MatrixClientPeg, update the Jitsi info await Jitsi.getInstance().start(); - RebrandListener.sharedInstance().start(); - // dispatch that we finished starting up to wire up any other bits // of the matrix client that cannot be set prior to starting up. dis.dispatch({action: 'client_started'}); @@ -710,7 +707,6 @@ export function stopMatrixClient(unsetClient=true) { IntegrationManagers.sharedInstance().stopWatching(); Mjolnir.sharedInstance().stop(); DeviceListener.sharedInstance().stop(); - RebrandListener.sharedInstance().stop(); if (DMRoomMap.shared()) DMRoomMap.shared().stop(); EventIndexPeg.stop(); const cli = MatrixClientPeg.get(); diff --git a/src/RebrandListener.tsx b/src/RebrandListener.tsx deleted file mode 100644 index 47b883cf35..0000000000 --- a/src/RebrandListener.tsx +++ /dev/null @@ -1,184 +0,0 @@ -/* -Copyright 2020 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import SdkConfig from "./SdkConfig"; -import ToastStore from "./stores/ToastStore"; -import GenericToast from "./components/views/toasts/GenericToast"; -import RebrandDialog from "./components/views/dialogs/RebrandDialog"; -import { RebrandDialogKind } from "./components/views/dialogs/RebrandDialog"; -import Modal from './Modal'; -import { _t } from './languageHandler'; - -const TOAST_KEY = 'rebrand'; -const NAG_INTERVAL = 24 * 60 * 60 * 1000; - -function getRedirectUrl(url): string { - const redirectUrl = new URL(url); - redirectUrl.hash = ''; - - if (SdkConfig.get()['redirectToNewBrandUrl']) { - const newUrl = new URL(SdkConfig.get()['redirectToNewBrandUrl']); - if (url.hostname !== newUrl.hostname || url.pathname !== newUrl.pathname) { - redirectUrl.hostname = newUrl.hostname; - redirectUrl.pathname = newUrl.pathname; - return redirectUrl.toString(); - } - return null; - } else if (url.hostname === 'riot.im') { - if (url.pathname.startsWith('/app')) { - redirectUrl.hostname = 'app.element.io'; - redirectUrl.pathname = '/'; - } else if (url.pathname.startsWith('/staging')) { - redirectUrl.hostname = 'staging.element.io'; - redirectUrl.pathname = '/'; - } else if (url.pathname.startsWith('/develop')) { - redirectUrl.hostname = 'develop.element.io'; - redirectUrl.pathname = '/'; - } - - return redirectUrl.href; - } else if (url.hostname.endsWith('.riot.im')) { - redirectUrl.hostname = url.hostname.substr(0, url.hostname.length - '.riot.im'.length) + '.element.io'; - return redirectUrl.href; - } else { - return null; - } -} - -/** - * Shows toasts informing the user that the name of the app has changed and, - * potentially, that they should head to a different URL and log in there - */ -export default class RebrandListener { - private _reshowTimer?: number; - private nagAgainAt?: number = null; - - static sharedInstance() { - if (!window.mxRebrandListener) window.mxRebrandListener = new RebrandListener(); - return window.mxRebrandListener; - } - - constructor() { - this._reshowTimer = null; - } - - start() { - this.recheck(); - } - - stop() { - if (this._reshowTimer) { - clearTimeout(this._reshowTimer); - this._reshowTimer = null; - } - } - - onNagToastLearnMore = async () => { - const [doneClicked] = await Modal.createDialog(RebrandDialog, { - kind: RebrandDialogKind.NAG, - targetUrl: getRedirectUrl(window.location), - }).finished; - if (doneClicked) { - // open in new tab: they should come back here & log out - window.open(getRedirectUrl(window.location), '_blank'); - } - - // whatever the user clicks, we go away & nag again after however long: - // If they went to the new URL, we want to nag them to log out if they - // come back to this tab, and if they clicked, 'remind me later' we want - // to, well, remind them later. - this.nagAgainAt = Date.now() + NAG_INTERVAL; - this.recheck(); - }; - - onOneTimeToastLearnMore = async () => { - const [doneClicked] = await Modal.createDialog(RebrandDialog, { - kind: RebrandDialogKind.ONE_TIME, - }).finished; - if (doneClicked) { - localStorage.setItem('mx_rename_dialog_dismissed', 'true'); - this.recheck(); - } - }; - - onOneTimeToastDismiss = async () => { - localStorage.setItem('mx_rename_dialog_dismissed', 'true'); - this.recheck(); - }; - - onNagTimerFired = () => { - this._reshowTimer = null; - this.nagAgainAt = null; - this.recheck(); - }; - - private async recheck() { - // There are two types of toast/dialog we show: a 'one time' informing the user that - // the app is now called a different thing but no action is required from them (they - // may need to look for a different name name/icon to launch the app but don't need to - // log in again) and a nag toast where they need to log in to the app on a different domain. - let nagToast = false; - let oneTimeToast = false; - - if (getRedirectUrl(window.location)) { - if (!this.nagAgainAt) { - // if we have redirectUrl, show the nag toast - nagToast = true; - } - } else { - // otherwise we show the 'one time' toast / dialog - const renameDialogDismissed = localStorage.getItem('mx_rename_dialog_dismissed'); - if (renameDialogDismissed !== 'true') { - oneTimeToast = true; - } - } - - if (nagToast || oneTimeToast) { - let description; - let rejectLabel = null; - let onReject = null; - if (nagToast) { - description = _t("Use your account to sign in to the latest version"); - } else { - description = _t("We’re excited to announce Riot is now Element"); - rejectLabel = _t("Dismiss"); - onReject = this.onOneTimeToastDismiss; - } - - ToastStore.sharedInstance().addOrReplaceToast({ - key: TOAST_KEY, - title: _t("Riot is now Element!"), - icon: 'element_logo', - props: { - description, - acceptLabel: _t("Learn More"), - onAccept: nagToast ? this.onNagToastLearnMore : this.onOneTimeToastLearnMore, - rejectLabel, - onReject, - }, - component: GenericToast, - priority: 20, - }); - } else { - ToastStore.sharedInstance().dismissToast(TOAST_KEY); - } - - if (!this._reshowTimer && this.nagAgainAt) { - // XXX: Our build system picks up NodeJS bindings when we need browser bindings. - this._reshowTimer = setTimeout(this.onNagTimerFired, (this.nagAgainAt - Date.now()) + 100) as any as number; - } - } -} diff --git a/src/components/views/dialogs/RebrandDialog.tsx b/src/components/views/dialogs/RebrandDialog.tsx deleted file mode 100644 index 79b4b69a4a..0000000000 --- a/src/components/views/dialogs/RebrandDialog.tsx +++ /dev/null @@ -1,116 +0,0 @@ -/* -Copyright 2020 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import * as React from 'react'; -import * as PropTypes from 'prop-types'; -import BaseDialog from './BaseDialog'; -import { _t } from '../../../languageHandler'; -import DialogButtons from '../elements/DialogButtons'; - -export enum RebrandDialogKind { - NAG, - ONE_TIME, -} - -interface IProps { - onFinished: (bool) => void; - kind: RebrandDialogKind; - targetUrl?: string; -} - -export default class RebrandDialog extends React.PureComponent { - private onDoneClick = () => { - this.props.onFinished(true); - }; - - private onGoToElementClick = () => { - this.props.onFinished(true); - }; - - private onRemindMeLaterClick = () => { - this.props.onFinished(false); - }; - - private getPrettyTargetUrl() { - const u = new URL(this.props.targetUrl); - let ret = u.host; - if (u.pathname !== '/') ret += u.pathname; - return ret; - } - - getBodyText() { - if (this.props.kind === RebrandDialogKind.NAG) { - return _t( - "Use your account to sign in to the latest version of the app at ", {}, - { - a: sub => {this.getPrettyTargetUrl()}, - }, - ); - } else { - return _t( - "You’re already signed in and good to go here, but you can also grab the latest " + - "versions of the app on all platforms at element.io/get-started.", {}, - { - a: sub => {sub}, - }, - ); - } - } - - getDialogButtons() { - if (this.props.kind === RebrandDialogKind.NAG) { - return ; - } else { - return ; - } - } - - render() { - return -
{this.getBodyText()}
-
- Riot Logo - - Element Logo -
-
- {_t( - "Learn more at element.io/previously-riot", {}, { - a: sub => {sub}, - } - )} -
- {this.getDialogButtons()} -
; - } -} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 974a96406f..006e7e67bf 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -117,10 +117,6 @@ "Unable to enable Notifications": "Unable to enable Notifications", "This email address was not found": "This email address was not found", "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Your email address does not appear to be associated with a Matrix ID on this Homeserver.", - "Use your account to sign in to the latest version": "Use your account to sign in to the latest version", - "We’re excited to announce Riot is now Element": "We’re excited to announce Riot is now Element", - "Riot is now Element!": "Riot is now Element!", - "Learn More": "Learn More", "Sign In or Create Account": "Sign In or Create Account", "Use your account or create a new one to continue.": "Use your account or create a new one to continue.", "Create Account": "Create Account", @@ -1720,11 +1716,6 @@ "Use this session to verify your new one, granting it access to encrypted messages:": "Use this session to verify your new one, granting it access to encrypted messages:", "If you didn’t sign in to this session, your account may be compromised.": "If you didn’t sign in to this session, your account may be compromised.", "This wasn't me": "This wasn't me", - "Use your account to sign in to the latest version of the app at ": "Use your account to sign in to the latest version of the app at ", - "You’re already signed in and good to go here, but you can also grab the latest versions of the app on all platforms at element.io/get-started.": "You’re already signed in and good to go here, but you can also grab the latest versions of the app on all platforms at element.io/get-started.", - "Go to Element": "Go to Element", - "We’re excited to announce Riot is now Element!": "We’re excited to announce Riot is now Element!", - "Learn more at element.io/previously-riot": "Learn more at element.io/previously-riot", "If you run into any bugs or have feedback you'd like to share, please let us know on GitHub.": "If you run into any bugs or have feedback you'd like to share, please let us know on GitHub.", "To help avoid duplicate issues, please view existing issues first (and add a +1) or create a new issue if you can't find it.": "To help avoid duplicate issues, please view existing issues first (and add a +1) or create a new issue if you can't find it.", "Report bugs & give feedback": "Report bugs & give feedback", From 83867b893fbbd6cc6a9e23a108f6dd6d63b624f0 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Wed, 12 Aug 2020 14:53:31 +0100 Subject: [PATCH 2/4] Update types --- src/@types/global.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 102643dd6a..6565b6549e 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -40,7 +40,6 @@ declare global { mxContentMessages: ContentMessages; mxToastStore: ToastStore; mxDeviceListener: DeviceListener; - mxRebrandListener: RebrandListener; mxRoomListStore: RoomListStoreClass; mxRoomListLayoutStore: RoomListLayoutStore; mxActiveRoomObserver: ActiveRoomObserver; From 1a68d2bb7c589d6d4cae51ff0e5a1bdbab873b0f Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Wed, 12 Aug 2020 14:57:26 +0100 Subject: [PATCH 3/4] Update more types --- src/@types/global.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 6565b6549e..13520e218d 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -19,7 +19,6 @@ import ContentMessages from "../ContentMessages"; import { IMatrixClientPeg } from "../MatrixClientPeg"; import ToastStore from "../stores/ToastStore"; import DeviceListener from "../DeviceListener"; -import RebrandListener from "../RebrandListener"; import { RoomListStoreClass } from "../stores/room-list/RoomListStore"; import { PlatformPeg } from "../PlatformPeg"; import RoomListLayoutStore from "../stores/room-list/RoomListLayoutStore"; From 2e76e19f37d47df09a79d2ac4cf93c2b6e34f1f4 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Wed, 12 Aug 2020 14:58:55 +0100 Subject: [PATCH 4/4] Remove rebrand toast from tests --- test/end-to-end-tests/src/scenarios/toast.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/test/end-to-end-tests/src/scenarios/toast.js b/test/end-to-end-tests/src/scenarios/toast.js index 2eafad8315..8b23dbcabc 100644 --- a/test/end-to-end-tests/src/scenarios/toast.js +++ b/test/end-to-end-tests/src/scenarios/toast.js @@ -24,12 +24,6 @@ module.exports = async function toastScenarios(alice, bob) { await rejectToast(alice, "Notifications"); alice.log.done(); - alice.log.step(`accepts rebrand toast`); - await acceptToast(alice, "Riot is now Element!"); - let doneButton = await alice.query('.mx_Dialog_primary'); - await doneButton.click(); // also accept the resulting dialog - alice.log.done(); - alice.log.step(`accepts analytics toast`); await acceptToast(alice, "Help us improve Element"); alice.log.done(); @@ -44,12 +38,6 @@ module.exports = async function toastScenarios(alice, bob) { await rejectToast(bob, "Notifications"); bob.log.done(); - bob.log.step(`accepts rebrand toast`); - await acceptToast(bob, "Riot is now Element!"); - doneButton = await bob.query('.mx_Dialog_primary'); - await doneButton.click(); // also accept the resulting dialog - bob.log.done(); - bob.log.step(`reject analytics toast`); await rejectToast(bob, "Help us improve Element"); bob.log.done();