From 08fadb092c930cc25323bba29ec8f5979f4dd9e2 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 22 May 2020 21:43:15 +0100 Subject: [PATCH 01/33] Remove redundant component Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../settings/EnableNotificationsButton.js | 75 ------------------- 1 file changed, 75 deletions(-) delete mode 100644 src/components/views/settings/EnableNotificationsButton.js diff --git a/src/components/views/settings/EnableNotificationsButton.js b/src/components/views/settings/EnableNotificationsButton.js deleted file mode 100644 index e4b348dfbd..0000000000 --- a/src/components/views/settings/EnableNotificationsButton.js +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright 2015, 2016 OpenMarket Ltd - -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 React from "react"; -import createReactClass from 'create-react-class'; -import Notifier from "../../../Notifier"; -import dis from "../../../dispatcher/dispatcher"; -import { _t } from '../../../languageHandler'; - -export default createReactClass({ - displayName: 'EnableNotificationsButton', - - componentDidMount: function() { - this.dispatcherRef = dis.register(this.onAction); - }, - - componentWillUnmount: function() { - dis.unregister(this.dispatcherRef); - }, - - onAction: function(payload) { - if (payload.action !== "notifier_enabled") { - return; - } - this.forceUpdate(); - }, - - enabled: function() { - return Notifier.isEnabled(); - }, - - onClick: function() { - const self = this; - if (!Notifier.supportsDesktopNotifications()) { - return; - } - if (!Notifier.isEnabled()) { - Notifier.setEnabled(true, function() { - self.forceUpdate(); - }); - } else { - Notifier.setEnabled(false); - } - this.forceUpdate(); - }, - - render: function() { - if (this.enabled()) { - return ( - - ); - } else { - return ( - - ); - } - }, -}); From a977b8c4ca12570919a1cf5deceaf71652648510 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 22 May 2020 21:55:43 +0100 Subject: [PATCH 02/33] Fix lifecycle to reset things before it starts them Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/Lifecycle.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Lifecycle.js b/src/Lifecycle.js index 22c5d48317..5fb54ede7f 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -575,10 +575,12 @@ async function startMatrixClient(startSyncing=true) { // to work). dis.dispatch({action: 'will_start_client'}, true); + // reset things first just in case + TypingStore.sharedInstance().reset(); + ToastStore.sharedInstance().reset(); + Notifier.start(); UserActivity.sharedInstance().start(); - TypingStore.sharedInstance().reset(); // just in case - ToastStore.sharedInstance().reset(); DMRoomMap.makeShared().start(); IntegrationManagers.sharedInstance().startWatching(); ActiveWidgetStore.start(); From 3732d1f5a5d0ad2fe22c73db924d612651967c79 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 22 May 2020 21:56:25 +0100 Subject: [PATCH 03/33] Migrate Desktop Notifications MatrixToolbar to a Toast Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/Notifier.js | 15 +++--- src/components/structures/LoggedInView.tsx | 7 +-- src/components/structures/MatrixChat.tsx | 6 --- src/components/views/globals/MatrixToolbar.js | 45 ----------------- src/toasts/DesktopNotificationsToast.ts | 50 +++++++++++++++++++ 5 files changed, 60 insertions(+), 63 deletions(-) delete mode 100644 src/components/views/globals/MatrixToolbar.js create mode 100644 src/toasts/DesktopNotificationsToast.ts diff --git a/src/Notifier.js b/src/Notifier.js index 2ffa92452b..cc804904e2 100644 --- a/src/Notifier.js +++ b/src/Notifier.js @@ -26,6 +26,10 @@ import * as sdk from './index'; import { _t } from './languageHandler'; import Modal from './Modal'; import SettingsStore, {SettingLevel} from "./settings/SettingsStore"; +import { + showToast as showNotificationsToast, + hideToast as hideNotificationsToast, +} from "./toasts/DesktopNotificationsToast"; /* * Dispatches: @@ -184,6 +188,10 @@ const Notifier = { MatrixClientPeg.get().on("sync", this.boundOnSyncStateChange); this.toolbarHidden = false; this.isSyncing = false; + + if (this.shouldShowToolbar()) { + showNotificationsToast(); + } }, stop: function() { @@ -278,12 +286,7 @@ const Notifier = { Analytics.trackEvent('Notifier', 'Set Toolbar Hidden', hidden); - // XXX: why are we dispatching this here? - // this is nothing to do with notifier_enabled - dis.dispatch({ - action: "notifier_enabled", - value: this.isEnabled(), - }); + hideNotificationsToast(); // update the info to localStorage for persistent settings if (persistent && global.localStorage) { diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index 148d10fe8d..0d3eda759e 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -68,7 +68,6 @@ interface IProps { showCookieBar: boolean; hasNewVersion: boolean; userHasGeneratedPassword: boolean; - showNotifierToolbar: boolean; page_type: string; autoJoin: boolean; thirdPartyInvite?: object; @@ -184,8 +183,7 @@ class LoggedInView extends React.PureComponent { if ( (prevProps.showCookieBar !== this.props.showCookieBar) || (prevProps.hasNewVersion !== this.props.hasNewVersion) || - (prevState.userHasGeneratedPassword !== this.state.userHasGeneratedPassword) || - (prevProps.showNotifierToolbar !== this.props.showNotifierToolbar) + (prevState.userHasGeneratedPassword !== this.state.userHasGeneratedPassword) ) { this.props.resizeNotifier.notifyBannersChanged(); } @@ -599,7 +597,6 @@ class LoggedInView extends React.PureComponent { const GroupView = sdk.getComponent('structures.GroupView'); const MyGroups = sdk.getComponent('structures.MyGroups'); const ToastContainer = sdk.getComponent('structures.ToastContainer'); - const MatrixToolbar = sdk.getComponent('globals.MatrixToolbar'); const CookieBar = sdk.getComponent('globals.CookieBar'); const NewVersionBar = sdk.getComponent('globals.NewVersionBar'); const UpdateCheckBar = sdk.getComponent('globals.UpdateCheckBar'); @@ -680,8 +677,6 @@ class LoggedInView extends React.PureComponent { topBar = ; } else if (this.state.userHasGeneratedPassword) { topBar = ; - } else if (this.props.showNotifierToolbar) { - topBar = ; } let bodyClasses = 'mx_MatrixChat'; diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index e6a56c683f..120497e5ef 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -184,7 +184,6 @@ interface IState { hideToSRUsers: boolean; syncError?: Error; resizeNotifier: ResizeNotifier; - showNotifierToolbar: boolean; serverConfig?: ValidatedServerConfig; ready: boolean; thirdPartyInvite?: object; @@ -238,7 +237,6 @@ export default class MatrixChat extends React.PureComponent { syncError: null, // If the current syncing status is ERROR, the error object, otherwise null. resizeNotifier: new ResizeNotifier(), - showNotifierToolbar: false, ready: false, }; @@ -686,9 +684,6 @@ export default class MatrixChat extends React.PureComponent { dis.dispatch({action: 'view_my_groups'}); } break; - case 'notifier_enabled': - this.setState({showNotifierToolbar: Notifier.shouldShowToolbar()}); - break; case 'hide_left_panel': this.setState({ collapseLhs: true, @@ -1381,7 +1376,6 @@ export default class MatrixChat extends React.PureComponent { dis.dispatch({action: 'focus_composer'}); this.setState({ ready: true, - showNotifierToolbar: Notifier.shouldShowToolbar(), }); }); cli.on('Call.incoming', function(call) { diff --git a/src/components/views/globals/MatrixToolbar.js b/src/components/views/globals/MatrixToolbar.js deleted file mode 100644 index 758e4d62aa..0000000000 --- a/src/components/views/globals/MatrixToolbar.js +++ /dev/null @@ -1,45 +0,0 @@ -/* -Copyright 2015, 2016 OpenMarket Ltd - -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 React from 'react'; -import createReactClass from 'create-react-class'; -import { _t } from '../../../languageHandler'; -import Notifier from '../../../Notifier'; -import AccessibleButton from '../../../components/views/elements/AccessibleButton'; - -export default createReactClass({ - displayName: 'MatrixToolbar', - - hideToolbar: function() { - Notifier.setToolbarHidden(true); - }, - - onClick: function() { - Notifier.setEnabled(true); - }, - - render: function() { - return ( -
- -
- { _t('You are not receiving desktop notifications') } { _t('Enable them now') } -
- {_t('Close')} -
- ); - }, -}); diff --git a/src/toasts/DesktopNotificationsToast.ts b/src/toasts/DesktopNotificationsToast.ts new file mode 100644 index 0000000000..02f0730759 --- /dev/null +++ b/src/toasts/DesktopNotificationsToast.ts @@ -0,0 +1,50 @@ +/* +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 { _t } from "../languageHandler"; +import Notifier from "../Notifier"; +import GenericToast from "../components/views/toasts/GenericToast"; +import ToastStore from "../stores/ToastStore"; + +const onAccept = () => { + Notifier.setEnabled(true); +}; + +const onReject = () => { + Notifier.setToolbarHidden(true); +}; + +const TOAST_KEY = "desktopnotifications"; + +export const showToast = () => { + ToastStore.sharedInstance().addOrReplaceToast({ + key: TOAST_KEY, + title: _t("Notifications"), + props: { + description: _t("You are not receiving desktop notifications"), + acceptLabel: _t("Enable them now"), + onAccept, + rejectLabel: _t("Close"), + onReject, + }, + component: GenericToast, + priority: 20, + }); +}; + +export const hideToast = () => { + ToastStore.sharedInstance().dismissToast(TOAST_KEY); +}; From 89292ca47be3fc0a714024a708452452e9938ee6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 22 May 2020 22:03:16 +0100 Subject: [PATCH 04/33] Fix toast priority sorting to put the highest priority into slot[0] Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/stores/ToastStore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/ToastStore.ts b/src/stores/ToastStore.ts index 4f6d2963c5..23317a0ad3 100644 --- a/src/stores/ToastStore.ts +++ b/src/stores/ToastStore.ts @@ -55,7 +55,7 @@ export default class ToastStore extends EventEmitter { const oldIndex = this.toasts.findIndex(t => t.key === newToast.key); if (oldIndex === -1) { let newIndex = this.toasts.length; - while (newIndex > 0 && this.toasts[newIndex - 1].priority > newToast.priority) --newIndex; + while (newIndex > 0 && this.toasts[newIndex - 1].priority < newToast.priority) --newIndex; this.toasts.splice(newIndex, 0, newToast); } else { this.toasts[oldIndex] = newToast; From c91f8c2631799d92cc582dbe6eebcdec3e0a2cb4 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 22 May 2020 22:04:21 +0100 Subject: [PATCH 05/33] Migrate Analytics Banner to a Toast Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/LoggedInView.tsx | 9 -- src/components/structures/MatrixChat.tsx | 28 ++---- src/components/views/globals/CookieBar.js | 103 --------------------- src/i18n/strings/en_EN.json | 14 +-- src/toasts/AnalyticsToast.tsx | 75 +++++++++++++++ 5 files changed, 92 insertions(+), 137 deletions(-) delete mode 100644 src/components/views/globals/CookieBar.js create mode 100644 src/toasts/AnalyticsToast.tsx diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index 0d3eda759e..88b64f0cbc 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -65,7 +65,6 @@ interface IProps { initialEventPixelOffset: number; leftDisabled: boolean; rightDisabled: boolean; - showCookieBar: boolean; hasNewVersion: boolean; userHasGeneratedPassword: boolean; page_type: string; @@ -181,7 +180,6 @@ class LoggedInView extends React.PureComponent { componentDidUpdate(prevProps, prevState) { // attempt to guess when a banner was opened or closed if ( - (prevProps.showCookieBar !== this.props.showCookieBar) || (prevProps.hasNewVersion !== this.props.hasNewVersion) || (prevState.userHasGeneratedPassword !== this.state.userHasGeneratedPassword) ) { @@ -597,7 +595,6 @@ class LoggedInView extends React.PureComponent { const GroupView = sdk.getComponent('structures.GroupView'); const MyGroups = sdk.getComponent('structures.MyGroups'); const ToastContainer = sdk.getComponent('structures.ToastContainer'); - const CookieBar = sdk.getComponent('globals.CookieBar'); const NewVersionBar = sdk.getComponent('globals.NewVersionBar'); const UpdateCheckBar = sdk.getComponent('globals.UpdateCheckBar'); const PasswordNagBar = sdk.getComponent('globals.PasswordNagBar'); @@ -663,12 +660,6 @@ class LoggedInView extends React.PureComponent { adminContact={usageLimitEvent.getContent().admin_contact} limitType={usageLimitEvent.getContent().limit_type} />; - } else if (this.props.showCookieBar && - this.props.config.piwik && - navigator.doNotTrack !== "1" - ) { - const policyUrl = this.props.config.piwik.policyUrl || null; - topBar = ; } else if (this.props.hasNewVersion) { topBar = { newVersionReleaseNotes: null, checkingForUpdate: null, - showCookieBar: false, - hideToSRUsers: false, syncError: null, // If the current syncing status is ERROR, the error object, otherwise null. @@ -337,12 +338,6 @@ export default class MatrixChat extends React.PureComponent { }); } - if (SettingsStore.getValue("showCookieBar")) { - this.setState({ - showCookieBar: true, - }); - } - if (SettingsStore.getValue("analyticsOptIn")) { Analytics.enable(); } @@ -756,19 +751,13 @@ export default class MatrixChat extends React.PureComponent { case 'accept_cookies': SettingsStore.setValue("analyticsOptIn", null, SettingLevel.DEVICE, true); SettingsStore.setValue("showCookieBar", null, SettingLevel.DEVICE, false); - - this.setState({ - showCookieBar: false, - }); + hideAnalyticsToast(); Analytics.enable(); break; case 'reject_cookies': SettingsStore.setValue("analyticsOptIn", null, SettingLevel.DEVICE, false); SettingsStore.setValue("showCookieBar", null, SettingLevel.DEVICE, false); - - this.setState({ - showCookieBar: false, - }); + hideAnalyticsToast(); break; } }; @@ -1246,6 +1235,10 @@ export default class MatrixChat extends React.PureComponent { } StorageManager.tryPersistStorage(); + + if (SettingsStore.getValue("showCookieBar") && this.props.config.piwik && navigator.doNotTrack !== "1") { + showAnalyticsToast(this.props.config.piwik && this.props.config.piwik.policyUrl); + } } private showScreenAfterLogin() { @@ -2031,7 +2024,6 @@ export default class MatrixChat extends React.PureComponent { onCloseAllSettings={this.onCloseAllSettings} onRegistered={this.onRegistered} currentRoomId={this.state.currentRoomId} - showCookieBar={this.state.showCookieBar} /> ); } else { diff --git a/src/components/views/globals/CookieBar.js b/src/components/views/globals/CookieBar.js deleted file mode 100644 index bf264686d0..0000000000 --- a/src/components/views/globals/CookieBar.js +++ /dev/null @@ -1,103 +0,0 @@ -/* -Copyright 2018 New Vector Ltd. - -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 React from 'react'; -import PropTypes from 'prop-types'; -import dis from '../../../dispatcher/dispatcher'; -import { _t } from '../../../languageHandler'; -import * as sdk from '../../../index'; -import Analytics from '../../../Analytics'; - -export default class CookieBar extends React.Component { - static propTypes = { - policyUrl: PropTypes.string, - } - - constructor() { - super(); - } - - onUsageDataClicked(e) { - e.stopPropagation(); - e.preventDefault(); - Analytics.showDetailsModal(); - } - - onAccept() { - dis.dispatch({ - action: 'accept_cookies', - }); - } - - onReject() { - dis.dispatch({ - action: 'reject_cookies', - }); - } - - render() { - const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); - const toolbarClasses = "mx_MatrixToolbar"; - return ( -
- -
- { this.props.policyUrl ? _t( - "Please help improve Riot.im by sending anonymous usage data. " + - "This will use a cookie " + - "(please see our Cookie Policy).", - {}, - { - 'UsageDataLink': (sub) => - { sub } - , - // XXX: We need to link to the page that explains our cookies - 'PolicyLink': (sub) => - { sub } - - , - }, - ) : _t( - "Please help improve Riot.im by sending anonymous usage data. " + - "This will use a cookie.", - {}, - { - 'UsageDataLink': (sub) => - { sub } - , - }, - ) } -
- - { _t("Yes, I want to help!") } - - - {_t('Close')} - -
- ); - } -} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 8ac05bf429..a79ee97109 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -391,10 +391,17 @@ "Common names and surnames are easy to guess": "Common names and surnames are easy to guess", "Straight rows of keys are easy to guess": "Straight rows of keys are easy to guess", "Short keyboard patterns are easy to guess": "Short keyboard patterns are easy to guess", + "Notifications": "Notifications", + "Send anonymous usage data which helps us improve Riot. This will use a cookie.": "Send anonymous usage data which helps us improve Riot. This will use a cookie.", + "I want to help": "I want to help", + "No": "No", "Review where you’re logged in": "Review where you’re logged in", "Verify all your sessions to ensure your account & messages are safe": "Verify all your sessions to ensure your account & messages are safe", "Review": "Review", "Later": "Later", + "You are not receiving desktop notifications": "You are not receiving desktop notifications", + "Enable them now": "Enable them now", + "Close": "Close", "Set up encryption": "Set up encryption", "Encryption upgrade available": "Encryption upgrade available", "Verify this session": "Verify this session", @@ -643,8 +650,6 @@ "Last seen": "Last seen", "Failed to set display name": "Failed to set display name", "Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.": "Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.", - "Disable Notifications": "Disable Notifications", - "Enable Notifications": "Enable Notifications", "Securely cache encrypted messages locally for them to appear in search results, using ": "Securely cache encrypted messages locally for them to appear in search results, using ", " to store messages from ": " to store messages from ", "rooms.": "rooms.", @@ -815,7 +820,6 @@ "Ban list rules - %(roomName)s": "Ban list rules - %(roomName)s", "Server rules": "Server rules", "User rules": "User rules", - "Close": "Close", "You have not ignored anyone.": "You have not ignored anyone.", "You are currently ignoring:": "You are currently ignoring:", "You are not subscribed to any lists": "You are not subscribed to any lists", @@ -836,7 +840,6 @@ "If this isn't what you want, please use a different tool to ignore users.": "If this isn't what you want, please use a different tool to ignore users.", "Room ID or alias of ban list": "Room ID or alias of ban list", "Subscribe": "Subscribe", - "Notifications": "Notifications", "Start automatically after system login": "Start automatically after system login", "Always show the window menu bar": "Always show the window menu bar", "Show tray icon and minimize window to it on close": "Show tray icon and minimize window to it on close", @@ -1287,7 +1290,6 @@ "Verify by emoji": "Verify by emoji", "Almost there! Is your other session showing the same shield?": "Almost there! Is your other session showing the same shield?", "Almost there! Is %(displayName)s showing the same shield?": "Almost there! Is %(displayName)s showing the same shield?", - "No": "No", "Yes": "Yes", "Verify all users in a room to ensure it's secure.": "Verify all users in a room to ensure it's secure.", "In encrypted rooms, verify all users to ensure it’s secure.": "In encrypted rooms, verify all users to ensure it’s secure.", @@ -1384,8 +1386,6 @@ "Please help improve Riot.im by sending anonymous usage data. This will use a cookie (please see our Cookie Policy).": "Please help improve Riot.im by sending anonymous usage data. This will use a cookie (please see our Cookie Policy).", "Please help improve Riot.im by sending anonymous usage data. This will use a cookie.": "Please help improve Riot.im by sending anonymous usage data. This will use a cookie.", "Yes, I want to help!": "Yes, I want to help!", - "You are not receiving desktop notifications": "You are not receiving desktop notifications", - "Enable them now": "Enable them now", "What's New": "What's New", "Update": "Update", "What's new?": "What's new?", diff --git a/src/toasts/AnalyticsToast.tsx b/src/toasts/AnalyticsToast.tsx new file mode 100644 index 0000000000..5b53a903fe --- /dev/null +++ b/src/toasts/AnalyticsToast.tsx @@ -0,0 +1,75 @@ +/* +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 React from "react"; + +import { _t } from "../languageHandler"; +import dis from "../dispatcher/dispatcher"; +import Analytics from "../Analytics"; +import AccessibleButton from "../components/views/elements/AccessibleButton"; +import GenericToast from "../components/views/toasts/GenericToast"; +import ToastStore from "../stores/ToastStore"; + +const onAccept = () => { + dis.dispatch({ + action: 'accept_cookies', + }); +}; + +const onReject = () => { + dis.dispatch({ + action: "reject_cookies", + }); +}; + +const onUsageDataClicked = () => { + Analytics.showDetailsModal(); +}; + +const TOAST_KEY = "analytics"; + +export const showToast = (policyUrl?: string) => { + ToastStore.sharedInstance().addOrReplaceToast({ + key: TOAST_KEY, + title: _t("Notifications"), + props: { + description: _t( + "Send anonymous usage data which helps us improve Riot. " + + "This will use a cookie.", + {}, + { + "UsageDataLink": (sub) => ( + { sub } + ), + // XXX: We need to link to the page that explains our cookies + "PolicyLink": (sub) => policyUrl ? ( + { sub } + ) : sub, + }, + ), + acceptLabel: _t("I want to help"), + onAccept, + rejectLabel: _t("No"), + onReject, + }, + component: GenericToast, + priority: 10, + }); +}; + +export const hideToast = () => { + ToastStore.sharedInstance().dismissToast(TOAST_KEY); +}; From 5d0040b8b36d1474db807748d1191844b424a569 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 22 May 2020 22:15:22 +0100 Subject: [PATCH 06/33] Migrate Password Nag Bar Banner to a Toast Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/LoggedInView.tsx | 22 ++++---- .../views/globals/PasswordNagBar.js | 53 ------------------- src/toasts/SetPasswordToast.ts | 47 ++++++++++++++++ 3 files changed, 58 insertions(+), 64 deletions(-) delete mode 100644 src/components/views/globals/PasswordNagBar.js create mode 100644 src/toasts/SetPasswordToast.ts diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index 88b64f0cbc..131e6a3867 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -43,6 +43,11 @@ import ResizeNotifier from "../../utils/ResizeNotifier"; import PlatformPeg from "../../PlatformPeg"; import { RoomListStoreTempProxy } from "../../stores/room-list/RoomListStoreTempProxy"; import { DefaultTagID } from "../../stores/room-list/models"; +import { + showToast as showSetPasswordToast, + hideToast as hideSetPasswordToast +} from "../../toasts/SetPasswordToast"; + // We need to fetch each pinned message individually (if we don't already have it) // so each pinned message may trigger a request. Limit the number per room for sanity. // NB. this is just for server notices rather than pinned messages in general. @@ -66,7 +71,6 @@ interface IProps { leftDisabled: boolean; rightDisabled: boolean; hasNewVersion: boolean; - userHasGeneratedPassword: boolean; page_type: string; autoJoin: boolean; thirdPartyInvite?: object; @@ -96,7 +100,6 @@ interface IState { syncErrorData: any; useCompactLayout: boolean; serverNoticeEvents: MatrixEvent[]; - userHasGeneratedPassword: boolean; } /** @@ -139,7 +142,6 @@ class LoggedInView extends React.PureComponent { this.state = { mouseDown: undefined, syncErrorData: undefined, - userHasGeneratedPassword: false, // use compact timeline view useCompactLayout: SettingsStore.getValue('useCompactLayout'), // any currently active server notice events @@ -180,8 +182,7 @@ class LoggedInView extends React.PureComponent { componentDidUpdate(prevProps, prevState) { // attempt to guess when a banner was opened or closed if ( - (prevProps.hasNewVersion !== this.props.hasNewVersion) || - (prevState.userHasGeneratedPassword !== this.state.userHasGeneratedPassword) + (prevProps.hasNewVersion !== this.props.hasNewVersion) ) { this.props.resizeNotifier.notifyBannersChanged(); } @@ -216,9 +217,11 @@ class LoggedInView extends React.PureComponent { }; _setStateFromSessionStore = () => { - this.setState({ - userHasGeneratedPassword: Boolean(this._sessionStore.getCachedPassword()), - }); + if (this._sessionStore.getCachedPassword()) { + showSetPasswordToast(); + } else { + hideSetPasswordToast(); + } }; _createResizer() { @@ -597,7 +600,6 @@ class LoggedInView extends React.PureComponent { const ToastContainer = sdk.getComponent('structures.ToastContainer'); const NewVersionBar = sdk.getComponent('globals.NewVersionBar'); const UpdateCheckBar = sdk.getComponent('globals.UpdateCheckBar'); - const PasswordNagBar = sdk.getComponent('globals.PasswordNagBar'); const ServerLimitBar = sdk.getComponent('globals.ServerLimitBar'); let pageElement; @@ -666,8 +668,6 @@ class LoggedInView extends React.PureComponent { />; } else if (this.props.checkingForUpdate) { topBar = ; - } else if (this.state.userHasGeneratedPassword) { - topBar = ; } let bodyClasses = 'mx_MatrixChat'; diff --git a/src/components/views/globals/PasswordNagBar.js b/src/components/views/globals/PasswordNagBar.js deleted file mode 100644 index 74735ca5ea..0000000000 --- a/src/components/views/globals/PasswordNagBar.js +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2017 Vector Creations Ltd -Copyright 2018 New Vector Ltd - -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 React from 'react'; -import createReactClass from 'create-react-class'; -import * as sdk from '../../../index'; -import Modal from '../../../Modal'; -import { _t } from '../../../languageHandler'; - -export default createReactClass({ - onUpdateClicked: function() { - const SetPasswordDialog = sdk.getComponent('dialogs.SetPasswordDialog'); - Modal.createTrackedDialog('Set Password Dialog', 'Password Nag Bar', SetPasswordDialog); - }, - - render: function() { - const toolbarClasses = "mx_MatrixToolbar mx_MatrixToolbar_clickable"; - return ( -
- -
- { _t( - "To return to your account in future you need to set a password", - {}, - { 'u': (sub) => { sub } }, - ) } -
- -
- ); - }, -}); diff --git a/src/toasts/SetPasswordToast.ts b/src/toasts/SetPasswordToast.ts new file mode 100644 index 0000000000..88cc317978 --- /dev/null +++ b/src/toasts/SetPasswordToast.ts @@ -0,0 +1,47 @@ +/* +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 { _t } from "../languageHandler"; +import Modal from "../Modal"; +import SetPasswordDialog from "../components/views/dialogs/SetPasswordDialog"; +import GenericToast from "../components/views/toasts/GenericToast"; +import ToastStore from "../stores/ToastStore"; + +const onAccept = () => { + Modal.createTrackedDialog('Set Password Dialog', 'Password Nag Bar', SetPasswordDialog); +}; + +const TOAST_KEY = "setpassword"; + +export const showToast = () => { + ToastStore.sharedInstance().addOrReplaceToast({ + key: TOAST_KEY, + title: _t("Set password"), + props: { + description: _t("To return to your account in future you need to set a password"), + acceptLabel: _t("Set Password"), + onAccept, + rejectLabel: _t("Later"), + onReject: hideToast, // it'll return on reload + }, + component: GenericToast, + priority: 60, + }); +}; + +export const hideToast = () => { + ToastStore.sharedInstance().dismissToast(TOAST_KEY); +}; From ccf9e6512341bb7395b1eba3841b0ce475379da5 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 22 May 2020 22:27:19 +0100 Subject: [PATCH 07/33] Migrate Server Limit Bar Banner to a Toast Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/LoggedInView.tsx | 56 ++++++----- .../views/globals/ServerLimitBar.js | 99 ------------------- src/toasts/ServerLimitToast.tsx | 50 ++++++++++ 3 files changed, 80 insertions(+), 125 deletions(-) delete mode 100644 src/components/views/globals/ServerLimitBar.js create mode 100644 src/toasts/ServerLimitToast.tsx diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index 131e6a3867..edb2482aa3 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -47,6 +47,10 @@ import { showToast as showSetPasswordToast, hideToast as hideSetPasswordToast } from "../../toasts/SetPasswordToast"; +import { + showToast as showServerLimitToast, + hideToast as hideServerLimitToast +} from "../../toasts/ServerLimitToast"; // We need to fetch each pinned message individually (if we don't already have it) // so each pinned message may trigger a request. Limit the number per room for sanity. @@ -99,7 +103,6 @@ interface IState { }; syncErrorData: any; useCompactLayout: boolean; - serverNoticeEvents: MatrixEvent[]; } /** @@ -144,8 +147,6 @@ class LoggedInView extends React.PureComponent { syncErrorData: undefined, // use compact timeline view useCompactLayout: SettingsStore.getValue('useCompactLayout'), - // any currently active server notice events - serverNoticeEvents: [], }; // stash the MatrixClient in case we log out before we are unmounted @@ -293,6 +294,8 @@ class LoggedInView extends React.PureComponent { if (oldSyncState === 'PREPARED' && syncState === 'SYNCING') { this._updateServerNoticeEvents(); + } else { + this._calculateServerLimitToast(data); } }; @@ -303,11 +306,24 @@ class LoggedInView extends React.PureComponent { } }; + _calculateServerLimitToast(syncErrorData, usageLimitEventContent?) { + const error = syncErrorData && syncErrorData.error && syncErrorData.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED"; + if (error) { + usageLimitEventContent = syncErrorData.error.data; + } + + if (usageLimitEventContent) { + showServerLimitToast(usageLimitEventContent.limit_type, usageLimitEventContent.admin_contact, error); + } else { + hideServerLimitToast(); + } + } + _updateServerNoticeEvents = async () => { const roomLists = RoomListStoreTempProxy.getRoomLists(); if (!roomLists[DefaultTagID.ServerNotice]) return []; - const pinnedEvents = []; + const events = []; for (const room of roomLists[DefaultTagID.ServerNotice]) { const pinStateEvent = room.currentState.getStateEvents("m.room.pinned_events", ""); @@ -317,12 +333,18 @@ class LoggedInView extends React.PureComponent { for (const eventId of pinnedEventIds) { const timeline = await this._matrixClient.getEventTimeline(room.getUnfilteredTimelineSet(), eventId, 0); const event = timeline.getEvents().find(ev => ev.getId() === eventId); - if (event) pinnedEvents.push(event); + if (event) events.push(event); } } - this.setState({ - serverNoticeEvents: pinnedEvents, + + const usageLimitEvent = events.find((e) => { + return ( + e && e.getType() === 'm.room.message' && + e.getContent()['server_notice_type'] === 'm.server_notice.usage_limit_reached' + ); }); + + this._calculateServerLimitToast(this.state.syncErrorData, usageLimitEvent && usageLimitEvent.getContent()); }; _onPaste = (ev) => { @@ -600,7 +622,6 @@ class LoggedInView extends React.PureComponent { const ToastContainer = sdk.getComponent('structures.ToastContainer'); const NewVersionBar = sdk.getComponent('globals.NewVersionBar'); const UpdateCheckBar = sdk.getComponent('globals.UpdateCheckBar'); - const ServerLimitBar = sdk.getComponent('globals.ServerLimitBar'); let pageElement; @@ -644,25 +665,8 @@ class LoggedInView extends React.PureComponent { break; } - const usageLimitEvent = this.state.serverNoticeEvents.find((e) => { - return ( - e && e.getType() === 'm.room.message' && - e.getContent()['server_notice_type'] === 'm.server_notice.usage_limit_reached' - ); - }); - let topBar; - if (this.state.syncErrorData && this.state.syncErrorData.error.errcode === 'M_RESOURCE_LIMIT_EXCEEDED') { - topBar = ; - } else if (usageLimitEvent) { - topBar = ; - } else if (this.props.hasNewVersion) { + if (this.props.hasNewVersion) { topBar = ; diff --git a/src/components/views/globals/ServerLimitBar.js b/src/components/views/globals/ServerLimitBar.js deleted file mode 100644 index 7d414a2826..0000000000 --- a/src/components/views/globals/ServerLimitBar.js +++ /dev/null @@ -1,99 +0,0 @@ -/* -Copyright 2018 New Vector Ltd - -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 React from 'react'; -import PropTypes from 'prop-types'; -import createReactClass from 'create-react-class'; -import classNames from 'classnames'; -import { _td } from '../../../languageHandler'; -import { messageForResourceLimitError } from '../../../utils/ErrorUtils'; - -export default createReactClass({ - propTypes: { - // 'hard' if the logged in user has been locked out, 'soft' if they haven't - kind: PropTypes.string, - adminContact: PropTypes.string, - // The type of limit that has been hit. - limitType: PropTypes.string.isRequired, - }, - - getDefaultProps: function() { - return { - kind: 'hard', - }; - }, - - render: function() { - const toolbarClasses = { - 'mx_MatrixToolbar': true, - }; - - let adminContact; - let limitError; - if (this.props.kind === 'hard') { - toolbarClasses['mx_MatrixToolbar_error'] = true; - - adminContact = messageForResourceLimitError( - this.props.limitType, - this.props.adminContact, - { - '': _td("Please contact your service administrator to continue using the service."), - }, - ); - limitError = messageForResourceLimitError( - this.props.limitType, - this.props.adminContact, - { - 'monthly_active_user': _td("This homeserver has hit its Monthly Active User limit."), - '': _td("This homeserver has exceeded one of its resource limits."), - }, - ); - } else { - toolbarClasses['mx_MatrixToolbar_info'] = true; - adminContact = messageForResourceLimitError( - this.props.limitType, - this.props.adminContact, - { - '': _td("Please contact your service administrator to get this limit increased."), - }, - ); - limitError = messageForResourceLimitError( - this.props.limitType, - this.props.adminContact, - { - 'monthly_active_user': _td( - "This homeserver has hit its Monthly Active User limit so " + - "some users will not be able to log in.", - ), - '': _td( - "This homeserver has exceeded one of its resource limits so " + - "some users will not be able to log in.", - ), - }, - {'b': sub => {sub}}, - ); - } - return ( -
-
- {limitError} - {' '} - {adminContact} -
-
- ); - }, -}); diff --git a/src/toasts/ServerLimitToast.tsx b/src/toasts/ServerLimitToast.tsx new file mode 100644 index 0000000000..f2de9e3499 --- /dev/null +++ b/src/toasts/ServerLimitToast.tsx @@ -0,0 +1,50 @@ +/* +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 React from "react"; + +import { _t, _td } from "../languageHandler"; +import GenericToast from "../components/views/toasts/GenericToast"; +import ToastStore from "../stores/ToastStore"; +import {messageForResourceLimitError} from "../utils/ErrorUtils"; + +const TOAST_KEY = "serverlimit"; + +export const showToast = (limitType: string, adminContact?: string, syncError?: boolean) => { + const errorText = messageForResourceLimitError(limitType, adminContact, { + 'monthly_active_user': _td("Your homeserver has exceeded its user limit."), + '': _td("Your homeserver has exceeded one of its resource limits."), + }); + const contactText = messageForResourceLimitError(limitType, adminContact, { + '': _td("Contact your server admin."), + }); + + ToastStore.sharedInstance().addOrReplaceToast({ + key: TOAST_KEY, + title: _t("Notifications"), + props: { + description: {errorText} {contactText}, + acceptLabel: _t("Ok"), + onAccept: hideToast, + }, + component: GenericToast, + priority: 20, + }); +}; + +export const hideToast = () => { + ToastStore.sharedInstance().dismissToast(TOAST_KEY); +}; From 29cfb47a83f5fc016f941a8387efb8f5a3e7463f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 22 May 2020 22:29:09 +0100 Subject: [PATCH 08/33] fix copy Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/toasts/AnalyticsToast.tsx | 2 +- src/toasts/ServerLimitToast.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/toasts/AnalyticsToast.tsx b/src/toasts/AnalyticsToast.tsx index 5b53a903fe..b186a65d9d 100644 --- a/src/toasts/AnalyticsToast.tsx +++ b/src/toasts/AnalyticsToast.tsx @@ -44,7 +44,7 @@ const TOAST_KEY = "analytics"; export const showToast = (policyUrl?: string) => { ToastStore.sharedInstance().addOrReplaceToast({ key: TOAST_KEY, - title: _t("Notifications"), + title: _t("Help us improve Riot"), props: { description: _t( "Send anonymous usage data which helps us improve Riot. " + diff --git a/src/toasts/ServerLimitToast.tsx b/src/toasts/ServerLimitToast.tsx index f2de9e3499..d35140be3d 100644 --- a/src/toasts/ServerLimitToast.tsx +++ b/src/toasts/ServerLimitToast.tsx @@ -34,14 +34,14 @@ export const showToast = (limitType: string, adminContact?: string, syncError?: ToastStore.sharedInstance().addOrReplaceToast({ key: TOAST_KEY, - title: _t("Notifications"), + title: _t("Warning"), props: { description: {errorText} {contactText}, acceptLabel: _t("Ok"), onAccept: hideToast, }, component: GenericToast, - priority: 20, + priority: 70, }); }; From 9f060d113259d3cf22d5e9ee4f6a98eb91c0d5d7 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 22 May 2020 22:34:32 +0100 Subject: [PATCH 09/33] i18n Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/en_EN.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a79ee97109..72c19587c8 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -391,7 +391,7 @@ "Common names and surnames are easy to guess": "Common names and surnames are easy to guess", "Straight rows of keys are easy to guess": "Straight rows of keys are easy to guess", "Short keyboard patterns are easy to guess": "Short keyboard patterns are easy to guess", - "Notifications": "Notifications", + "Help us improve Riot": "Help us improve Riot", "Send anonymous usage data which helps us improve Riot. This will use a cookie.": "Send anonymous usage data which helps us improve Riot. This will use a cookie.", "I want to help": "I want to help", "No": "No", @@ -399,9 +399,18 @@ "Verify all your sessions to ensure your account & messages are safe": "Verify all your sessions to ensure your account & messages are safe", "Review": "Review", "Later": "Later", + "Notifications": "Notifications", "You are not receiving desktop notifications": "You are not receiving desktop notifications", "Enable them now": "Enable them now", "Close": "Close", + "Your homeserver has exceeded its user limit.": "Your homeserver has exceeded its user limit.", + "Your homeserver has exceeded one of its resource limits.": "Your homeserver has exceeded one of its resource limits.", + "Contact your server admin.": "Contact your server admin.", + "Warning": "Warning", + "Ok": "Ok", + "Set password": "Set password", + "To return to your account in future you need to set a password": "To return to your account in future you need to set a password", + "Set Password": "Set Password", "Set up encryption": "Set up encryption", "Encryption upgrade available": "Encryption upgrade available", "Verify this session": "Verify this session", @@ -781,7 +790,6 @@ "Account management": "Account management", "Deactivating your account is a permanent action - be careful!": "Deactivating your account is a permanent action - be careful!", "Deactivate Account": "Deactivate Account", - "Warning": "Warning", "General": "General", "Discovery": "Discovery", "Deactivate account": "Deactivate account", @@ -1383,18 +1391,10 @@ "Something went wrong when trying to get your communities.": "Something went wrong when trying to get your communities.", "Display your community flair in rooms configured to show it.": "Display your community flair in rooms configured to show it.", "You're not currently a member of any communities.": "You're not currently a member of any communities.", - "Please help improve Riot.im by sending anonymous usage data. This will use a cookie (please see our Cookie Policy).": "Please help improve Riot.im by sending anonymous usage data. This will use a cookie (please see our Cookie Policy).", - "Please help improve Riot.im by sending anonymous usage data. This will use a cookie.": "Please help improve Riot.im by sending anonymous usage data. This will use a cookie.", - "Yes, I want to help!": "Yes, I want to help!", "What's New": "What's New", "Update": "Update", "What's new?": "What's new?", "A new version of Riot is available.": "A new version of Riot is available.", - "To return to your account in future you need to set a password": "To return to your account in future you need to set a password", - "Set Password": "Set Password", - "Please contact your service administrator to get this limit increased.": "Please contact your service administrator to get this limit increased.", - "This homeserver has hit its Monthly Active User limit so some users will not be able to log in.": "This homeserver has hit its Monthly Active User limit so some users will not be able to log in.", - "This homeserver has exceeded one of its resource limits so some users will not be able to log in.": "This homeserver has exceeded one of its resource limits so some users will not be able to log in.", "Error encountered (%(errorDetail)s).": "Error encountered (%(errorDetail)s).", "Checking for an update...": "Checking for an update...", "No update available.": "No update available.", From 891ba1bbe3c34bf5651846d425c07d969fec7cb7 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 22 May 2020 23:08:45 +0100 Subject: [PATCH 10/33] Replace New Version Bar with a Toast discards the `new_version` dispatch Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/views/globals/_MatrixToolbar.scss | 4 - src/components/structures/LoggedInView.tsx | 11 +- src/components/structures/MatrixChat.tsx | 21 ---- src/components/views/globals/NewVersionBar.js | 108 ------------------ src/i18n/strings/en_EN.json | 10 +- src/toasts/UpdateToast.tsx | 90 +++++++++++++++ 6 files changed, 99 insertions(+), 145 deletions(-) delete mode 100644 src/components/views/globals/NewVersionBar.js create mode 100644 src/toasts/UpdateToast.tsx diff --git a/res/css/views/globals/_MatrixToolbar.scss b/res/css/views/globals/_MatrixToolbar.scss index 5fdf572f99..07b92a7235 100644 --- a/res/css/views/globals/_MatrixToolbar.scss +++ b/res/css/views/globals/_MatrixToolbar.scss @@ -67,7 +67,3 @@ limitations under the License. .mx_MatrixToolbar_action { margin-right: 16px; } - -.mx_MatrixToolbar_changelog { - white-space: pre; -} diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index edb2482aa3..2a17233ec6 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -74,7 +74,6 @@ interface IProps { initialEventPixelOffset: number; leftDisabled: boolean; rightDisabled: boolean; - hasNewVersion: boolean; page_type: string; autoJoin: boolean; thirdPartyInvite?: object; @@ -96,6 +95,7 @@ interface IProps { newVersion?: string; newVersionReleaseNotes?: string; } + interface IState { mouseDown?: { x: number; @@ -183,7 +183,7 @@ class LoggedInView extends React.PureComponent { componentDidUpdate(prevProps, prevState) { // attempt to guess when a banner was opened or closed if ( - (prevProps.hasNewVersion !== this.props.hasNewVersion) + (prevProps.checkingForUpdate !== this.props.checkingForUpdate) ) { this.props.resizeNotifier.notifyBannersChanged(); } @@ -620,7 +620,6 @@ class LoggedInView extends React.PureComponent { const GroupView = sdk.getComponent('structures.GroupView'); const MyGroups = sdk.getComponent('structures.MyGroups'); const ToastContainer = sdk.getComponent('structures.ToastContainer'); - const NewVersionBar = sdk.getComponent('globals.NewVersionBar'); const UpdateCheckBar = sdk.getComponent('globals.UpdateCheckBar'); let pageElement; @@ -666,11 +665,7 @@ class LoggedInView extends React.PureComponent { } let topBar; - if (this.props.hasNewVersion) { - topBar = ; - } else if (this.props.checkingForUpdate) { + if (this.props.checkingForUpdate) { topBar = ; } diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index c69911fe04..f4d31708fe 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -173,10 +173,6 @@ interface IState { leftDisabled: boolean; middleDisabled: boolean; // the right panel's disabled state is tracked in its store. - version?: string; - newVersion?: string; - hasNewVersion: boolean; - newVersionReleaseNotes?: string; checkingForUpdate?: string; // updateCheckStatusEnum // Parameters used in the registration dance with the IS register_client_secret?: string; @@ -230,7 +226,6 @@ export default class MatrixChat extends React.PureComponent { leftDisabled: false, middleDisabled: false, - hasNewVersion: false, newVersionReleaseNotes: null, checkingForUpdate: null, @@ -726,12 +721,6 @@ export default class MatrixChat extends React.PureComponent { case 'client_started': this.onClientStarted(); break; - case 'new_version': - this.onVersion( - payload.currentVersion, payload.newVersion, - payload.releaseNotes, - ); - break; case 'check_updates': this.setState({ checkingForUpdate: payload.value }); break; @@ -1820,16 +1809,6 @@ export default class MatrixChat extends React.PureComponent { this.showScreen("settings"); }; - onVersion(current: string, latest: string, releaseNotes?: string) { - this.setState({ - version: current, - newVersion: latest, - hasNewVersion: current !== latest, - newVersionReleaseNotes: releaseNotes, - checkingForUpdate: null, - }); - } - onSendEvent(roomId: string, event: MatrixEvent) { const cli = MatrixClientPeg.get(); if (!cli) { diff --git a/src/components/views/globals/NewVersionBar.js b/src/components/views/globals/NewVersionBar.js deleted file mode 100644 index dedccdc6b6..0000000000 --- a/src/components/views/globals/NewVersionBar.js +++ /dev/null @@ -1,108 +0,0 @@ -/* -Copyright 2015, 2016 OpenMarket Ltd -Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> - -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 React from 'react'; -import PropTypes from 'prop-types'; -import createReactClass from 'create-react-class'; -import * as sdk from '../../../index'; -import Modal from '../../../Modal'; -import PlatformPeg from '../../../PlatformPeg'; -import { _t } from '../../../languageHandler'; - -/** - * Check a version string is compatible with the Changelog - * dialog ([vectorversion]-react-[react-sdk-version]-js-[js-sdk-version]) - */ -function checkVersion(ver) { - const parts = ver.split('-'); - return parts.length == 5 && parts[1] == 'react' && parts[3] == 'js'; -} - -export default createReactClass({ - propTypes: { - version: PropTypes.string.isRequired, - newVersion: PropTypes.string.isRequired, - releaseNotes: PropTypes.string, - }, - - displayReleaseNotes: function(releaseNotes) { - const QuestionDialog = sdk.getComponent('dialogs.QuestionDialog'); - Modal.createTrackedDialog('Display release notes', '', QuestionDialog, { - title: _t("What's New"), - description:
{releaseNotes}
, - button: _t("Update"), - onFinished: (update) => { - if (update && PlatformPeg.get()) { - PlatformPeg.get().installUpdate(); - } - }, - }); - }, - - displayChangelog: function() { - const ChangelogDialog = sdk.getComponent('dialogs.ChangelogDialog'); - Modal.createTrackedDialog('Display Changelog', '', ChangelogDialog, { - version: this.props.version, - newVersion: this.props.newVersion, - onFinished: (update) => { - if (update && PlatformPeg.get()) { - PlatformPeg.get().installUpdate(); - } - }, - }); - }, - - onUpdateClicked: function() { - PlatformPeg.get().installUpdate(); - }, - - render: function() { - let action_button; - // If we have release notes to display, we display them. Otherwise, - // we display the Changelog Dialog which takes two versions and - // automatically tells you what's changed (provided the versions - // are in the right format) - if (this.props.releaseNotes) { - action_button = ( - - ); - } else if (checkVersion(this.props.version) && checkVersion(this.props.newVersion)) { - action_button = ( - - ); - } else if (PlatformPeg.get()) { - action_button = ( - - ); - } - return ( -
- -
- {_t("A new version of Riot is available.")} -
- {action_button} -
- ); - }, -}); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 72c19587c8..0170aee17a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -421,6 +421,12 @@ "Other users may not trust it": "Other users may not trust it", "New login. Was this you?": "New login. Was this you?", "Verify the new login accessing your account: %(name)s": "Verify the new login accessing your account: %(name)s", + "What's New": "What's New", + "Update": "Update", + "What's new?": "What's new?", + "Restart": "Restart", + "Upgrade your Riot": "Upgrade your Riot", + "A new version of Riot is available!": "A new version of Riot is available!", "There was an error joining the room": "There was an error joining the room", "Sorry, your homeserver is too old to participate in this room.": "Sorry, your homeserver is too old to participate in this room.", "Please contact your homeserver administrator.": "Please contact your homeserver administrator.", @@ -1391,10 +1397,6 @@ "Something went wrong when trying to get your communities.": "Something went wrong when trying to get your communities.", "Display your community flair in rooms configured to show it.": "Display your community flair in rooms configured to show it.", "You're not currently a member of any communities.": "You're not currently a member of any communities.", - "What's New": "What's New", - "Update": "Update", - "What's new?": "What's new?", - "A new version of Riot is available.": "A new version of Riot is available.", "Error encountered (%(errorDetail)s).": "Error encountered (%(errorDetail)s).", "Checking for an update...": "Checking for an update...", "No update available.": "No update available.", diff --git a/src/toasts/UpdateToast.tsx b/src/toasts/UpdateToast.tsx new file mode 100644 index 0000000000..3d4b55a4ff --- /dev/null +++ b/src/toasts/UpdateToast.tsx @@ -0,0 +1,90 @@ +/* +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 React from "react"; + +import { _t } from "../languageHandler"; +import GenericToast from "../components/views/toasts/GenericToast"; +import ToastStore from "../stores/ToastStore"; +import QuestionDialog from "../components/views/dialogs/QuestionDialog"; +import ChangelogDialog from "../components/views/dialogs/ChangelogDialog"; +import PlatformPeg from "../PlatformPeg"; +import Modal from "../Modal"; + +const TOAST_KEY = "update"; + +/* + * Check a version string is compatible with the Changelog + * dialog ([riot-version]-react-[react-sdk-version]-js-[js-sdk-version]) + */ +function checkVersion(ver) { + const parts = ver.split('-'); + return parts.length === 5 && parts[1] === 'react' && parts[3] === 'js'; +} + +function installUpdate() { + PlatformPeg.get().installUpdate(); +} + +export const showToast = (version: string, newVersion: string, releaseNotes?: string) => { + let onAccept; + let acceptLabel = _t("What's new?"); + if (releaseNotes) { + onAccept = () => { + Modal.createTrackedDialog('Display release notes', '', QuestionDialog, { + title: _t("What's New"), + description:
{releaseNotes}
, + button: _t("Update"), + onFinished: (update) => { + if (update && PlatformPeg.get()) { + PlatformPeg.get().installUpdate(); + } + }, + }); + }; + } else if (checkVersion(version) && checkVersion(newVersion)) { + onAccept = () => { + Modal.createTrackedDialog('Display Changelog', '', ChangelogDialog, { + version, + newVersion, + onFinished: (update) => { + if (update && PlatformPeg.get()) { + PlatformPeg.get().installUpdate(); + } + }, + }); + }; + } else { + onAccept = installUpdate; + acceptLabel = _t("Restart"); + } + + ToastStore.sharedInstance().addOrReplaceToast({ + key: TOAST_KEY, + title: _t("Upgrade your Riot"), + props: { + description: _t("A new version of Riot is available!"), + acceptLabel, + onAccept, + }, + component: GenericToast, + priority: 20, + }); +}; + +export const hideToast = () => { + ToastStore.sharedInstance().dismissToast(TOAST_KEY); +}; From 41934268087fa0b9be828f1714eb4a5e3ab6f28a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 22 May 2020 23:14:33 +0100 Subject: [PATCH 11/33] delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/LoggedInView.tsx | 3 --- src/components/structures/MatrixChat.tsx | 1 - 2 files changed, 4 deletions(-) diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index 2a17233ec6..df21768da5 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -91,9 +91,6 @@ interface IProps { currentUserId?: string; currentGroupId?: string; currentGroupIsNew?: boolean; - version?: string; - newVersion?: string; - newVersionReleaseNotes?: string; } interface IState { diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index f4d31708fe..e6db42af1d 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -226,7 +226,6 @@ export default class MatrixChat extends React.PureComponent { leftDisabled: false, middleDisabled: false, - newVersionReleaseNotes: null, checkingForUpdate: null, hideToSRUsers: false, From 3d2b56aecd38ea399f2666b688c4007438384411 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 22 May 2020 23:23:23 +0100 Subject: [PATCH 12/33] i18n Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/en_EN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 0170aee17a..97ada284b0 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -421,9 +421,9 @@ "Other users may not trust it": "Other users may not trust it", "New login. Was this you?": "New login. Was this you?", "Verify the new login accessing your account: %(name)s": "Verify the new login accessing your account: %(name)s", + "What's new?": "What's new?", "What's New": "What's New", "Update": "Update", - "What's new?": "What's new?", "Restart": "Restart", "Upgrade your Riot": "Upgrade your Riot", "A new version of Riot is available!": "A new version of Riot is available!", From fb73bac4cf7c847d088be2f02414c82c4eeee041 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 26 May 2020 13:53:28 +0100 Subject: [PATCH 13/33] Update UpdateToast's priority to 30 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/toasts/UpdateToast.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/toasts/UpdateToast.tsx b/src/toasts/UpdateToast.tsx index 3d4b55a4ff..55c128e86a 100644 --- a/src/toasts/UpdateToast.tsx +++ b/src/toasts/UpdateToast.tsx @@ -81,7 +81,7 @@ export const showToast = (version: string, newVersion: string, releaseNotes?: st onAccept, }, component: GenericToast, - priority: 20, + priority: 30, }); }; From 254ed4b1b60c1bf8964a67febf2761a22773802b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 11:33:42 +0100 Subject: [PATCH 14/33] Add debug lined to figure out e2e test failure Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/stores/ToastStore.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/stores/ToastStore.ts b/src/stores/ToastStore.ts index e963ecd736..a26c5e0794 100644 --- a/src/stores/ToastStore.ts +++ b/src/stores/ToastStore.ts @@ -56,6 +56,7 @@ export default class ToastStore extends EventEmitter { * @param {object} newToast The new toast */ addOrReplaceToast>(newToast: IToast) { + console.log("DEBUG addOrReplaceToast", newToast.key, JSON.stringify(newToast)); const oldIndex = this.toasts.findIndex(t => t.key === newToast.key); if (oldIndex === -1) { let newIndex = this.toasts.length; @@ -68,6 +69,7 @@ export default class ToastStore extends EventEmitter { } dismissToast(key) { + console.log("DEBUG dismissToast", key); const length = this.toasts.length; this.toasts = this.toasts.filter(t => t.key !== key); if (length !== this.toasts.length) { From 3dade4e759bc4d01af126e1f3a5d64c4057b1d20 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 11:48:48 +0100 Subject: [PATCH 15/33] tweak Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/stores/ToastStore.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/stores/ToastStore.ts b/src/stores/ToastStore.ts index a26c5e0794..2f5a1f74b0 100644 --- a/src/stores/ToastStore.ts +++ b/src/stores/ToastStore.ts @@ -70,13 +70,15 @@ export default class ToastStore extends EventEmitter { dismissToast(key) { console.log("DEBUG dismissToast", key); + if (this.toasts[0] && this.toasts[0].key === key) { + this.countSeen++; + } + const length = this.toasts.length; this.toasts = this.toasts.filter(t => t.key !== key); if (length !== this.toasts.length) { if (this.toasts.length === 0) { this.countSeen = 0; - } else { - this.countSeen++; } this.emit('update'); From efa47f1a8e948e2920aa640cccfad94caa9942b5 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 12:02:51 +0100 Subject: [PATCH 16/33] Change out debug Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.tsx | 1 + src/stores/ToastStore.ts | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index f2d7e81d85..f8c96ee393 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -624,6 +624,7 @@ export default class MatrixChat extends React.PureComponent { break; } case 'view_room_directory': { + console.log("DEBUG view_room_directory"); const RoomDirectory = sdk.getComponent("structures.RoomDirectory"); Modal.createTrackedDialog('Room directory', '', RoomDirectory, {}, 'mx_RoomDirectory_dialogWrapper', false, true); diff --git a/src/stores/ToastStore.ts b/src/stores/ToastStore.ts index 2f5a1f74b0..55c48c3937 100644 --- a/src/stores/ToastStore.ts +++ b/src/stores/ToastStore.ts @@ -56,7 +56,6 @@ export default class ToastStore extends EventEmitter { * @param {object} newToast The new toast */ addOrReplaceToast>(newToast: IToast) { - console.log("DEBUG addOrReplaceToast", newToast.key, JSON.stringify(newToast)); const oldIndex = this.toasts.findIndex(t => t.key === newToast.key); if (oldIndex === -1) { let newIndex = this.toasts.length; @@ -69,7 +68,6 @@ export default class ToastStore extends EventEmitter { } dismissToast(key) { - console.log("DEBUG dismissToast", key); if (this.toasts[0] && this.toasts[0].key === key) { this.countSeen++; } From 48de17457663867359b511344210d5d962200d29 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 12:20:20 +0100 Subject: [PATCH 17/33] remove debug Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index f8c96ee393..f2d7e81d85 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -624,7 +624,6 @@ export default class MatrixChat extends React.PureComponent { break; } case 'view_room_directory': { - console.log("DEBUG view_room_directory"); const RoomDirectory = sdk.getComponent("structures.RoomDirectory"); Modal.createTrackedDialog('Room directory', '', RoomDirectory, {}, 'mx_RoomDirectory_dialogWrapper', false, true); From b7c688d3282d5156c74f9ac50e0780908c895965 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 12:40:38 +0100 Subject: [PATCH 18/33] test e2e tests workaround Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/end-to-end-tests/src/usecases/join.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/end-to-end-tests/src/usecases/join.js b/test/end-to-end-tests/src/usecases/join.js index 655c0be686..10a48bd71c 100644 --- a/test/end-to-end-tests/src/usecases/join.js +++ b/test/end-to-end-tests/src/usecases/join.js @@ -19,6 +19,15 @@ const {openRoomDirectory} = require('./create-room'); module.exports = async function join(session, roomName) { session.log.step(`joins room "${roomName}"`); + while (true) { + try { + const toastDismissButton = await session.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger'); + await toastDismissButton.click(); + } catch (e) { + break; + } + } + await openRoomDirectory(session); const roomInput = await session.query('.mx_DirectorySearchBox input'); await session.replaceInputText(roomInput, roomName); From 7b6d49c416f63576fcdf3be088b80cc2b87bde71 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 12:57:45 +0100 Subject: [PATCH 19/33] e2e test toasts Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/end-to-end-tests/src/scenario.js | 2 + test/end-to-end-tests/src/scenarios/toast.js | 23 ++++++++++ test/end-to-end-tests/src/usecases/join.js | 9 ---- test/end-to-end-tests/src/usecases/toasts.js | 45 ++++++++++++++++++++ 4 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 test/end-to-end-tests/src/scenarios/toast.js create mode 100644 test/end-to-end-tests/src/usecases/toasts.js diff --git a/test/end-to-end-tests/src/scenario.js b/test/end-to-end-tests/src/scenario.js index f575fb392e..2191d630ac 100644 --- a/test/end-to-end-tests/src/scenario.js +++ b/test/end-to-end-tests/src/scenario.js @@ -17,6 +17,7 @@ limitations under the License. const {range} = require('./util'); const signup = require('./usecases/signup'); +const toastScenarios = require('./scenarios/toast'); const roomDirectoryScenarios = require('./scenarios/directory'); const lazyLoadingScenarios = require('./scenarios/lazy-loading'); const e2eEncryptionScenarios = require('./scenarios/e2e-encryption'); @@ -37,6 +38,7 @@ module.exports = async function scenario(createSession, restCreator) { const alice = await createUser("alice"); const bob = await createUser("bob"); + await toastScenarios(alice, bob); await roomDirectoryScenarios(alice, bob); await e2eEncryptionScenarios(alice, bob); console.log("create REST users:"); diff --git a/test/end-to-end-tests/src/scenarios/toast.js b/test/end-to-end-tests/src/scenarios/toast.js new file mode 100644 index 0000000000..91c6ed750f --- /dev/null +++ b/test/end-to-end-tests/src/scenarios/toast.js @@ -0,0 +1,23 @@ +/* +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. +*/ + +const {acceptToast} = require("../usecases/toasts"); + +module.exports = async function toastScenarios(alice, bob) { + console.log(" checking and clearing all toasts:"); + await acceptToast(alice, "Help us improve Riot"); + await acceptToast(bob, "Help us improve Riot"); +}; diff --git a/test/end-to-end-tests/src/usecases/join.js b/test/end-to-end-tests/src/usecases/join.js index 10a48bd71c..655c0be686 100644 --- a/test/end-to-end-tests/src/usecases/join.js +++ b/test/end-to-end-tests/src/usecases/join.js @@ -19,15 +19,6 @@ const {openRoomDirectory} = require('./create-room'); module.exports = async function join(session, roomName) { session.log.step(`joins room "${roomName}"`); - while (true) { - try { - const toastDismissButton = await session.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger'); - await toastDismissButton.click(); - } catch (e) { - break; - } - } - await openRoomDirectory(session); const roomInput = await session.query('.mx_DirectorySearchBox input'); await session.replaceInputText(roomInput, roomName); diff --git a/test/end-to-end-tests/src/usecases/toasts.js b/test/end-to-end-tests/src/usecases/toasts.js new file mode 100644 index 0000000000..663484ce6e --- /dev/null +++ b/test/end-to-end-tests/src/usecases/toasts.js @@ -0,0 +1,45 @@ +/* +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. +*/ + +const assert = require('assert'); + +async function assertToast(session, expectedTitle) { + const h2Element = await session.query('.mx_Toast_title h2'); + const toastTitle = await session.innerText(h2Element); + assert(toastTitle, expectedTitle); +} + +async function acceptToast(session, expectedTitle) { + const foundToast = await assertToast(session, expectedTitle); + if (!foundToast) { + throw new Error("could not find expected toast"); + } + + const btn = await session.query('.mx_Toast_buttons .mx_AccessibleButton_kind_primary'); + await btn.click(); +} + +async function rejectToast(session, expectedTitle) { + const foundToast = await assertToast(session, expectedTitle); + if (!foundToast) { + throw new Error("could not find expected toast"); + } + + const btn = await session.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger'); + await btn.click(); +} + +module.exports = {assertToast, acceptToast, rejectToast}; From d9552c7f5c4296ee92258614c261cb3d01352d4f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 13:10:28 +0100 Subject: [PATCH 20/33] e2e test toasts v2 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/end-to-end-tests/src/scenarios/toast.js | 12 ++++++++++-- test/end-to-end-tests/src/usecases/toasts.js | 12 ++---------- 2 files changed, 12 insertions(+), 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 91c6ed750f..9a0594cc31 100644 --- a/test/end-to-end-tests/src/scenarios/toast.js +++ b/test/end-to-end-tests/src/scenarios/toast.js @@ -14,10 +14,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -const {acceptToast} = require("../usecases/toasts"); +const {acceptToast, rejectToast} = require("../usecases/toasts"); module.exports = async function toastScenarios(alice, bob) { console.log(" checking and clearing all toasts:"); + + alice.log.startGroup(`clears toasts`); + await acceptToast(alice, "Notifications"); await acceptToast(alice, "Help us improve Riot"); - await acceptToast(bob, "Help us improve Riot"); + alice.log.endGroup(); + + bob.log.startGroup(`clears toasts`); + await rejectToast(bob, "Notifications"); + await rejectToast(bob, "Help us improve Riot"); + bob.log.endGroup(); }; diff --git a/test/end-to-end-tests/src/usecases/toasts.js b/test/end-to-end-tests/src/usecases/toasts.js index 663484ce6e..991d3cc39c 100644 --- a/test/end-to-end-tests/src/usecases/toasts.js +++ b/test/end-to-end-tests/src/usecases/toasts.js @@ -23,21 +23,13 @@ async function assertToast(session, expectedTitle) { } async function acceptToast(session, expectedTitle) { - const foundToast = await assertToast(session, expectedTitle); - if (!foundToast) { - throw new Error("could not find expected toast"); - } - + await assertToast(session, expectedTitle); const btn = await session.query('.mx_Toast_buttons .mx_AccessibleButton_kind_primary'); await btn.click(); } async function rejectToast(session, expectedTitle) { - const foundToast = await assertToast(session, expectedTitle); - if (!foundToast) { - throw new Error("could not find expected toast"); - } - + await assertToast(session, expectedTitle); const btn = await session.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger'); await btn.click(); } From 37c875b8635107eb966a692141deed915d14669e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 13:23:49 +0100 Subject: [PATCH 21/33] improve end to end tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/end-to-end-tests/src/scenarios/toast.js | 10 ++++++++-- test/end-to-end-tests/src/usecases/toasts.js | 7 ++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/test/end-to-end-tests/src/scenarios/toast.js b/test/end-to-end-tests/src/scenarios/toast.js index 9a0594cc31..b5b7fa4494 100644 --- a/test/end-to-end-tests/src/scenarios/toast.js +++ b/test/end-to-end-tests/src/scenarios/toast.js @@ -14,18 +14,24 @@ See the License for the specific language governing permissions and limitations under the License. */ -const {acceptToast, rejectToast} = require("../usecases/toasts"); +const {assertNoToasts, acceptToast, rejectToast} = require("../usecases/toasts"); module.exports = async function toastScenarios(alice, bob) { - console.log(" checking and clearing all toasts:"); + console.log(" checking and clearing toasts:"); alice.log.startGroup(`clears toasts`); + alice.log.step(`accepts desktop notifications toast`); await acceptToast(alice, "Notifications"); + alice.log.step(`accepts analytics toast`); await acceptToast(alice, "Help us improve Riot"); + await assertNoToasts(alice); alice.log.endGroup(); bob.log.startGroup(`clears toasts`); + alice.log.step(`reject desktop notifications toast`); await rejectToast(bob, "Notifications"); + alice.log.step(`reject analytics toast`); await rejectToast(bob, "Help us improve Riot"); + await assertNoToasts(bob); bob.log.endGroup(); }; diff --git a/test/end-to-end-tests/src/usecases/toasts.js b/test/end-to-end-tests/src/usecases/toasts.js index 991d3cc39c..636714d66b 100644 --- a/test/end-to-end-tests/src/usecases/toasts.js +++ b/test/end-to-end-tests/src/usecases/toasts.js @@ -16,6 +16,11 @@ limitations under the License. const assert = require('assert'); +async function assertNoToasts(session) { + const toast = await session.query('.mx_Toast_toast'); + assert(!toast, 'toast found when none expected'); +} + async function assertToast(session, expectedTitle) { const h2Element = await session.query('.mx_Toast_title h2'); const toastTitle = await session.innerText(h2Element); @@ -34,4 +39,4 @@ async function rejectToast(session, expectedTitle) { await btn.click(); } -module.exports = {assertToast, acceptToast, rejectToast}; +module.exports = {assertNoToasts, assertToast, acceptToast, rejectToast}; From faaca43a75f5281ceb335ef1e9514836c0d8c396 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 13:35:15 +0100 Subject: [PATCH 22/33] more loggin' Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/end-to-end-tests/src/scenarios/toast.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/test/end-to-end-tests/src/scenarios/toast.js b/test/end-to-end-tests/src/scenarios/toast.js index b5b7fa4494..ee3f2954f3 100644 --- a/test/end-to-end-tests/src/scenarios/toast.js +++ b/test/end-to-end-tests/src/scenarios/toast.js @@ -20,18 +20,32 @@ module.exports = async function toastScenarios(alice, bob) { console.log(" checking and clearing toasts:"); alice.log.startGroup(`clears toasts`); + alice.log.step(`accepts desktop notifications toast`); await acceptToast(alice, "Notifications"); + alice.log.done(); + alice.log.step(`accepts analytics toast`); await acceptToast(alice, "Help us improve Riot"); + alice.log.done(); + + alice.log.step(`checks no remaining toasts`); await assertNoToasts(alice); + alice.log.done(); alice.log.endGroup(); bob.log.startGroup(`clears toasts`); - alice.log.step(`reject desktop notifications toast`); + + bob.log.step(`reject desktop notifications toast`); await rejectToast(bob, "Notifications"); - alice.log.step(`reject analytics toast`); + bob.log.done(); + + bob.log.step(`reject analytics toast`); await rejectToast(bob, "Help us improve Riot"); + bob.log.done(); + + bob.log.step(`checks no remaining toasts`); await assertNoToasts(bob); + bob.log.done(); bob.log.endGroup(); }; From 841ce74ac2fde0201b1b698a0b096fd5f5158467 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 13:39:00 +0100 Subject: [PATCH 23/33] Fix assert vs assert.equal Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/end-to-end-tests/src/usecases/dialog.js | 2 +- test/end-to-end-tests/src/usecases/toasts.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/end-to-end-tests/src/usecases/dialog.js b/test/end-to-end-tests/src/usecases/dialog.js index d4ae97dff9..15ac50bb18 100644 --- a/test/end-to-end-tests/src/usecases/dialog.js +++ b/test/end-to-end-tests/src/usecases/dialog.js @@ -20,7 +20,7 @@ const assert = require('assert'); async function assertDialog(session, expectedTitle) { const titleElement = await session.query(".mx_Dialog .mx_Dialog_title"); const dialogHeader = await session.innerText(titleElement); - assert(dialogHeader, expectedTitle); + assert.equal(dialogHeader, expectedTitle); } async function acceptDialog(session, expectedTitle) { diff --git a/test/end-to-end-tests/src/usecases/toasts.js b/test/end-to-end-tests/src/usecases/toasts.js index 636714d66b..a82c910eea 100644 --- a/test/end-to-end-tests/src/usecases/toasts.js +++ b/test/end-to-end-tests/src/usecases/toasts.js @@ -24,7 +24,7 @@ async function assertNoToasts(session) { async function assertToast(session, expectedTitle) { const h2Element = await session.query('.mx_Toast_title h2'); const toastTitle = await session.innerText(h2Element); - assert(toastTitle, expectedTitle); + assert.equal(toastTitle, expectedTitle); } async function acceptToast(session, expectedTitle) { From 627b5685887d02ed31f8c1fbecc45f48d8edbbbe Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 13:48:20 +0100 Subject: [PATCH 24/33] check if it is a race Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/end-to-end-tests/src/scenarios/toast.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/end-to-end-tests/src/scenarios/toast.js b/test/end-to-end-tests/src/scenarios/toast.js index ee3f2954f3..980ee4b33f 100644 --- a/test/end-to-end-tests/src/scenarios/toast.js +++ b/test/end-to-end-tests/src/scenarios/toast.js @@ -29,6 +29,7 @@ module.exports = async function toastScenarios(alice, bob) { await acceptToast(alice, "Help us improve Riot"); alice.log.done(); + await alice.delay(300); alice.log.step(`checks no remaining toasts`); await assertNoToasts(alice); alice.log.done(); @@ -44,6 +45,7 @@ module.exports = async function toastScenarios(alice, bob) { await rejectToast(bob, "Help us improve Riot"); bob.log.done(); + await bob.delay(300); bob.log.step(`checks no remaining toasts`); await assertNoToasts(bob); bob.log.done(); From 61066b0c4c915285f2bb0e5bf8c123cadbcab1f6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 14:27:09 +0100 Subject: [PATCH 25/33] test it again Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/end-to-end-tests/src/scenarios/toast.js | 22 ++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/test/end-to-end-tests/src/scenarios/toast.js b/test/end-to-end-tests/src/scenarios/toast.js index 980ee4b33f..34b979f09a 100644 --- a/test/end-to-end-tests/src/scenarios/toast.js +++ b/test/end-to-end-tests/src/scenarios/toast.js @@ -20,7 +20,6 @@ module.exports = async function toastScenarios(alice, bob) { console.log(" checking and clearing toasts:"); alice.log.startGroup(`clears toasts`); - alice.log.step(`accepts desktop notifications toast`); await acceptToast(alice, "Notifications"); alice.log.done(); @@ -29,14 +28,21 @@ module.exports = async function toastScenarios(alice, bob) { await acceptToast(alice, "Help us improve Riot"); alice.log.done(); - await alice.delay(300); + while (true) { + try { + const toastDismissButton = await alice.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger'); + await toastDismissButton.click(); + } catch (e) { + break; + } + } + alice.log.step(`checks no remaining toasts`); await assertNoToasts(alice); alice.log.done(); alice.log.endGroup(); bob.log.startGroup(`clears toasts`); - bob.log.step(`reject desktop notifications toast`); await rejectToast(bob, "Notifications"); bob.log.done(); @@ -45,7 +51,15 @@ module.exports = async function toastScenarios(alice, bob) { await rejectToast(bob, "Help us improve Riot"); bob.log.done(); - await bob.delay(300); + while (true) { + try { + const toastDismissButton = await bob.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger'); + await toastDismissButton.click(); + } catch (e) { + break; + } + } + bob.log.step(`checks no remaining toasts`); await assertNoToasts(bob); bob.log.done(); From 91811581bc9412d48842a7341c8f3c33a5623170 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 14:35:59 +0100 Subject: [PATCH 26/33] fix assertNoToasts Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/end-to-end-tests/src/usecases/toasts.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/end-to-end-tests/src/usecases/toasts.js b/test/end-to-end-tests/src/usecases/toasts.js index a82c910eea..2e88677e4b 100644 --- a/test/end-to-end-tests/src/usecases/toasts.js +++ b/test/end-to-end-tests/src/usecases/toasts.js @@ -17,8 +17,12 @@ limitations under the License. const assert = require('assert'); async function assertNoToasts(session) { - const toast = await session.query('.mx_Toast_toast'); - assert(!toast, 'toast found when none expected'); + try { + await session.query('.mx_Toast_toast'); + } catch (e) { + return; + } + throw new Error('toast found when none expected'); } async function assertToast(session, expectedTitle) { From f3dfdbe74644f974b855a8d494ecbc4d205fd93b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 14:36:44 +0100 Subject: [PATCH 27/33] debug Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/end-to-end-tests/src/scenarios/toast.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/end-to-end-tests/src/scenarios/toast.js b/test/end-to-end-tests/src/scenarios/toast.js index 34b979f09a..f528e993c3 100644 --- a/test/end-to-end-tests/src/scenarios/toast.js +++ b/test/end-to-end-tests/src/scenarios/toast.js @@ -30,6 +30,9 @@ module.exports = async function toastScenarios(alice, bob) { while (true) { try { + const h2Element = await alice.query('.mx_Toast_title h2'); + const toastTitle = await alice.innerText(h2Element); + console.log("DEBUG closing", toastTitle); const toastDismissButton = await alice.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger'); await toastDismissButton.click(); } catch (e) { @@ -53,6 +56,9 @@ module.exports = async function toastScenarios(alice, bob) { while (true) { try { + const h2Element = await bob.query('.mx_Toast_title h2'); + const toastTitle = await bob.innerText(h2Element); + console.log("DEBUG closing", toastTitle); const toastDismissButton = await bob.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger'); await toastDismissButton.click(); } catch (e) { From 63ac1cb4ab583de0eb2869be09f6fc76877f0f37 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 14:56:24 +0100 Subject: [PATCH 28/33] debug some more Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/end-to-end-tests/src/scenarios/toast.js | 28 ++++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/end-to-end-tests/src/scenarios/toast.js b/test/end-to-end-tests/src/scenarios/toast.js index f528e993c3..97b5caa14f 100644 --- a/test/end-to-end-tests/src/scenarios/toast.js +++ b/test/end-to-end-tests/src/scenarios/toast.js @@ -20,13 +20,13 @@ module.exports = async function toastScenarios(alice, bob) { console.log(" checking and clearing toasts:"); alice.log.startGroup(`clears toasts`); - alice.log.step(`accepts desktop notifications toast`); - await acceptToast(alice, "Notifications"); - alice.log.done(); - - alice.log.step(`accepts analytics toast`); - await acceptToast(alice, "Help us improve Riot"); - alice.log.done(); + // alice.log.step(`accepts desktop notifications toast`); + // await acceptToast(alice, "Notifications"); + // alice.log.done(); + // + // alice.log.step(`accepts analytics toast`); + // await acceptToast(alice, "Help us improve Riot"); + // alice.log.done(); while (true) { try { @@ -46,13 +46,13 @@ module.exports = async function toastScenarios(alice, bob) { alice.log.endGroup(); bob.log.startGroup(`clears toasts`); - bob.log.step(`reject desktop notifications toast`); - await rejectToast(bob, "Notifications"); - bob.log.done(); - - bob.log.step(`reject analytics toast`); - await rejectToast(bob, "Help us improve Riot"); - bob.log.done(); + // bob.log.step(`reject desktop notifications toast`); + // await rejectToast(bob, "Notifications"); + // bob.log.done(); + // + // bob.log.step(`reject analytics toast`); + // await rejectToast(bob, "Help us improve Riot"); + // bob.log.done(); while (true) { try { From cb07fa53f4282ebfe8f12d63f93bba8344f62b9e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 15:05:40 +0100 Subject: [PATCH 29/33] test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/end-to-end-tests/src/scenarios/toast.js | 48 +++++--------------- 1 file changed, 12 insertions(+), 36 deletions(-) diff --git a/test/end-to-end-tests/src/scenarios/toast.js b/test/end-to-end-tests/src/scenarios/toast.js index 97b5caa14f..02496f398d 100644 --- a/test/end-to-end-tests/src/scenarios/toast.js +++ b/test/end-to-end-tests/src/scenarios/toast.js @@ -20,25 +20,13 @@ module.exports = async function toastScenarios(alice, bob) { console.log(" checking and clearing toasts:"); alice.log.startGroup(`clears toasts`); - // alice.log.step(`accepts desktop notifications toast`); - // await acceptToast(alice, "Notifications"); - // alice.log.done(); - // - // alice.log.step(`accepts analytics toast`); - // await acceptToast(alice, "Help us improve Riot"); - // alice.log.done(); + alice.log.step(`accepts desktop notifications toast`); + await acceptToast(alice, "Notifications"); + alice.log.done(); - while (true) { - try { - const h2Element = await alice.query('.mx_Toast_title h2'); - const toastTitle = await alice.innerText(h2Element); - console.log("DEBUG closing", toastTitle); - const toastDismissButton = await alice.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger'); - await toastDismissButton.click(); - } catch (e) { - break; - } - } + alice.log.step(`rejects analytics toast`); + await rejectToast(alice, "Help us improve Riot"); + alice.log.done(); alice.log.step(`checks no remaining toasts`); await assertNoToasts(alice); @@ -46,25 +34,13 @@ module.exports = async function toastScenarios(alice, bob) { alice.log.endGroup(); bob.log.startGroup(`clears toasts`); - // bob.log.step(`reject desktop notifications toast`); - // await rejectToast(bob, "Notifications"); - // bob.log.done(); - // - // bob.log.step(`reject analytics toast`); - // await rejectToast(bob, "Help us improve Riot"); - // bob.log.done(); + bob.log.step(`reject desktop notifications toast`); + await rejectToast(bob, "Notifications"); + bob.log.done(); - while (true) { - try { - const h2Element = await bob.query('.mx_Toast_title h2'); - const toastTitle = await bob.innerText(h2Element); - console.log("DEBUG closing", toastTitle); - const toastDismissButton = await bob.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger'); - await toastDismissButton.click(); - } catch (e) { - break; - } - } + bob.log.step(`reject analytics toast`); + await rejectToast(bob, "Help us improve Riot"); + bob.log.done(); bob.log.step(`checks no remaining toasts`); await assertNoToasts(bob); From e35c9d5bbf5eec8e55a6485b275559ef39d7625f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 15:18:43 +0100 Subject: [PATCH 30/33] more testing Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/toasts/AnalyticsToast.tsx | 2 + test/end-to-end-tests/src/scenarios/toast.js | 48 +++++++++++++++----- test/end-to-end-tests/src/usecases/toasts.js | 5 +- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/toasts/AnalyticsToast.tsx b/src/toasts/AnalyticsToast.tsx index b186a65d9d..7cd59222dd 100644 --- a/src/toasts/AnalyticsToast.tsx +++ b/src/toasts/AnalyticsToast.tsx @@ -24,12 +24,14 @@ import GenericToast from "../components/views/toasts/GenericToast"; import ToastStore from "../stores/ToastStore"; const onAccept = () => { + console.log("DEBUG onAccept AnalyticsToast"); dis.dispatch({ action: 'accept_cookies', }); }; const onReject = () => { + console.log("DEBUG onReject AnalyticsToast"); dis.dispatch({ action: "reject_cookies", }); diff --git a/test/end-to-end-tests/src/scenarios/toast.js b/test/end-to-end-tests/src/scenarios/toast.js index 02496f398d..97b5caa14f 100644 --- a/test/end-to-end-tests/src/scenarios/toast.js +++ b/test/end-to-end-tests/src/scenarios/toast.js @@ -20,13 +20,25 @@ module.exports = async function toastScenarios(alice, bob) { console.log(" checking and clearing toasts:"); alice.log.startGroup(`clears toasts`); - alice.log.step(`accepts desktop notifications toast`); - await acceptToast(alice, "Notifications"); - alice.log.done(); + // alice.log.step(`accepts desktop notifications toast`); + // await acceptToast(alice, "Notifications"); + // alice.log.done(); + // + // alice.log.step(`accepts analytics toast`); + // await acceptToast(alice, "Help us improve Riot"); + // alice.log.done(); - alice.log.step(`rejects analytics toast`); - await rejectToast(alice, "Help us improve Riot"); - alice.log.done(); + while (true) { + try { + const h2Element = await alice.query('.mx_Toast_title h2'); + const toastTitle = await alice.innerText(h2Element); + console.log("DEBUG closing", toastTitle); + const toastDismissButton = await alice.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger'); + await toastDismissButton.click(); + } catch (e) { + break; + } + } alice.log.step(`checks no remaining toasts`); await assertNoToasts(alice); @@ -34,13 +46,25 @@ module.exports = async function toastScenarios(alice, bob) { alice.log.endGroup(); bob.log.startGroup(`clears toasts`); - bob.log.step(`reject desktop notifications toast`); - await rejectToast(bob, "Notifications"); - bob.log.done(); + // bob.log.step(`reject desktop notifications toast`); + // await rejectToast(bob, "Notifications"); + // bob.log.done(); + // + // bob.log.step(`reject analytics toast`); + // await rejectToast(bob, "Help us improve Riot"); + // bob.log.done(); - bob.log.step(`reject analytics toast`); - await rejectToast(bob, "Help us improve Riot"); - bob.log.done(); + while (true) { + try { + const h2Element = await bob.query('.mx_Toast_title h2'); + const toastTitle = await bob.innerText(h2Element); + console.log("DEBUG closing", toastTitle); + const toastDismissButton = await bob.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger'); + await toastDismissButton.click(); + } catch (e) { + break; + } + } bob.log.step(`checks no remaining toasts`); await assertNoToasts(bob); diff --git a/test/end-to-end-tests/src/usecases/toasts.js b/test/end-to-end-tests/src/usecases/toasts.js index 2e88677e4b..75142ed08f 100644 --- a/test/end-to-end-tests/src/usecases/toasts.js +++ b/test/end-to-end-tests/src/usecases/toasts.js @@ -22,7 +22,10 @@ async function assertNoToasts(session) { } catch (e) { return; } - throw new Error('toast found when none expected'); + + const h2Element = await session.query('.mx_Toast_title h2'); + const toastTitle = await session.innerText(h2Element); + throw new Error(`"${toastTitle}" toast found when none expected`); } async function assertToast(session, expectedTitle) { From 7486338efaa31e9e2657a5458e86388c2a9e5536 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 16:51:04 +0100 Subject: [PATCH 31/33] Fix.the.tests. Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/end-to-end-tests/src/scenarios/toast.js | 48 +++++--------------- test/end-to-end-tests/src/session.js | 4 +- test/end-to-end-tests/src/usecases/toasts.js | 9 ++-- 3 files changed, 18 insertions(+), 43 deletions(-) diff --git a/test/end-to-end-tests/src/scenarios/toast.js b/test/end-to-end-tests/src/scenarios/toast.js index 97b5caa14f..1206ef40b0 100644 --- a/test/end-to-end-tests/src/scenarios/toast.js +++ b/test/end-to-end-tests/src/scenarios/toast.js @@ -20,25 +20,13 @@ module.exports = async function toastScenarios(alice, bob) { console.log(" checking and clearing toasts:"); alice.log.startGroup(`clears toasts`); - // alice.log.step(`accepts desktop notifications toast`); - // await acceptToast(alice, "Notifications"); - // alice.log.done(); - // - // alice.log.step(`accepts analytics toast`); - // await acceptToast(alice, "Help us improve Riot"); - // alice.log.done(); + alice.log.step(`reject desktop notifications toast`); + await rejectToast(alice, "Notifications"); + alice.log.done(); - while (true) { - try { - const h2Element = await alice.query('.mx_Toast_title h2'); - const toastTitle = await alice.innerText(h2Element); - console.log("DEBUG closing", toastTitle); - const toastDismissButton = await alice.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger'); - await toastDismissButton.click(); - } catch (e) { - break; - } - } + alice.log.step(`accepts analytics toast`); + await acceptToast(alice, "Help us improve Riot"); + alice.log.done(); alice.log.step(`checks no remaining toasts`); await assertNoToasts(alice); @@ -46,25 +34,13 @@ module.exports = async function toastScenarios(alice, bob) { alice.log.endGroup(); bob.log.startGroup(`clears toasts`); - // bob.log.step(`reject desktop notifications toast`); - // await rejectToast(bob, "Notifications"); - // bob.log.done(); - // - // bob.log.step(`reject analytics toast`); - // await rejectToast(bob, "Help us improve Riot"); - // bob.log.done(); + bob.log.step(`reject desktop notifications toast`); + await rejectToast(bob, "Notifications"); + bob.log.done(); - while (true) { - try { - const h2Element = await bob.query('.mx_Toast_title h2'); - const toastTitle = await bob.innerText(h2Element); - console.log("DEBUG closing", toastTitle); - const toastDismissButton = await bob.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger'); - await toastDismissButton.click(); - } catch (e) { - break; - } - } + bob.log.step(`reject analytics toast`); + await rejectToast(bob, "Help us improve Riot"); + bob.log.done(); bob.log.step(`checks no remaining toasts`); await assertNoToasts(bob); diff --git a/test/end-to-end-tests/src/session.js b/test/end-to-end-tests/src/session.js index 55c2ed440c..907ee2fb8e 100644 --- a/test/end-to-end-tests/src/session.js +++ b/test/end-to-end-tests/src/session.js @@ -122,8 +122,8 @@ module.exports = class RiotSession { await input.type(text); } - query(selector, timeout = DEFAULT_TIMEOUT) { - return this.page.waitForSelector(selector, {visible: true, timeout}); + query(selector, timeout = DEFAULT_TIMEOUT, hidden = false) { + return this.page.waitForSelector(selector, {visible: true, timeout, hidden}); } async queryAll(selector) { diff --git a/test/end-to-end-tests/src/usecases/toasts.js b/test/end-to-end-tests/src/usecases/toasts.js index 75142ed08f..204ed2b983 100644 --- a/test/end-to-end-tests/src/usecases/toasts.js +++ b/test/end-to-end-tests/src/usecases/toasts.js @@ -18,14 +18,13 @@ const assert = require('assert'); async function assertNoToasts(session) { try { - await session.query('.mx_Toast_toast'); + await session.query('.mx_Toast_toast', 1000, true); } catch (e) { - return; + const h2Element = await session.query('.mx_Toast_title h2', 1000); + const toastTitle = await session.innerText(h2Element); + throw new Error(`"${toastTitle}" toast found when none expected`); } - const h2Element = await session.query('.mx_Toast_title h2'); - const toastTitle = await session.innerText(h2Element); - throw new Error(`"${toastTitle}" toast found when none expected`); } async function assertToast(session, expectedTitle) { From 71108fcf393e4648d1dfc1fd17e0b50c8423ed12 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 27 May 2020 17:02:32 +0100 Subject: [PATCH 32/33] delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/end-to-end-tests/src/usecases/toasts.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/end-to-end-tests/src/usecases/toasts.js b/test/end-to-end-tests/src/usecases/toasts.js index 204ed2b983..db78352f2b 100644 --- a/test/end-to-end-tests/src/usecases/toasts.js +++ b/test/end-to-end-tests/src/usecases/toasts.js @@ -24,7 +24,6 @@ async function assertNoToasts(session) { const toastTitle = await session.innerText(h2Element); throw new Error(`"${toastTitle}" toast found when none expected`); } - } async function assertToast(session, expectedTitle) { From c4d6367a178b2df35d628e4060028fd3aa2eb93d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 28 May 2020 17:30:43 +0100 Subject: [PATCH 33/33] Swap priorities of Desktop Notifications and Update toasts Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/toasts/DesktopNotificationsToast.ts | 2 +- src/toasts/UpdateToast.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/toasts/DesktopNotificationsToast.ts b/src/toasts/DesktopNotificationsToast.ts index 02f0730759..413e82e20b 100644 --- a/src/toasts/DesktopNotificationsToast.ts +++ b/src/toasts/DesktopNotificationsToast.ts @@ -41,7 +41,7 @@ export const showToast = () => { onReject, }, component: GenericToast, - priority: 20, + priority: 30, }); }; diff --git a/src/toasts/UpdateToast.tsx b/src/toasts/UpdateToast.tsx index 55c128e86a..3d4b55a4ff 100644 --- a/src/toasts/UpdateToast.tsx +++ b/src/toasts/UpdateToast.tsx @@ -81,7 +81,7 @@ export const showToast = (version: string, newVersion: string, releaseNotes?: st onAccept, }, component: GenericToast, - priority: 30, + priority: 20, }); };