From 67ef52b7f8a3729fe279ac07643ea52628dc211a Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski Date: Fri, 22 Jul 2022 14:25:35 +0200 Subject: [PATCH] Implement button to return to user onboarding screen --- res/css/_components.pcss | 1 + .../_UserOnboardingButton.pcss | 68 +++++++++++++++ src/components/structures/LeftPanel.tsx | 7 ++ src/components/structures/LoggedInView.tsx | 1 + .../tabs/user/PreferencesUserSettingsTab.tsx | 1 + .../user-onboarding/UserOnboardingButton.tsx | 87 +++++++++++++++++++ src/i18n/strings/en_EN.json | 2 + src/settings/Settings.tsx | 5 ++ 8 files changed, 172 insertions(+) create mode 100644 res/css/views/user-onboarding/_UserOnboardingButton.pcss create mode 100644 src/components/views/user-onboarding/UserOnboardingButton.tsx diff --git a/res/css/_components.pcss b/res/css/_components.pcss index 3525aa2ba0f8..8db58ea624c7 100644 --- a/res/css/_components.pcss +++ b/res/css/_components.pcss @@ -328,6 +328,7 @@ @import "./views/user-onboarding/_UserOnboardingList.pcss"; @import "./views/user-onboarding/_UserOnboardingPage.pcss"; @import "./views/user-onboarding/_UserOnboardingTask.pcss"; +@import "./views/user-onboarding/_UserOnboardingButton.pcss"; @import "./views/verification/_VerificationShowSas.pcss"; @import "./views/voip/CallView/_CallViewButtons.pcss"; @import "./views/voip/_CallPreview.pcss"; diff --git a/res/css/views/user-onboarding/_UserOnboardingButton.pcss b/res/css/views/user-onboarding/_UserOnboardingButton.pcss new file mode 100644 index 000000000000..40516b0f2bb8 --- /dev/null +++ b/res/css/views/user-onboarding/_UserOnboardingButton.pcss @@ -0,0 +1,68 @@ +.mx_UserOnboardingButton { + display: flex; + flex-direction: column; + align-content: stretch; + align-items: stretch; + border-radius: 8px; + margin: $spacing-8 $spacing-8 0; + padding: $spacing-12; + + &.mx_UserOnboardingButton_selected, + &:hover, + &:focus-within { + background-color: $panel-actions; + } + + .mx_UserOnboardingButton_content { + display: flex; + flex-direction: row; + gap: 5px; + align-items: center; + + .mx_Heading_h4 { + margin-right: auto; + font-size: $font-14px; + color: $primary-content; + } + + .mx_UserOnboardingButton_percentage { + font-size: $font-12px; + color: $secondary-content; + } + + .mx_UserOnboardingButton_close { + position: relative; + box-sizing: border-box; + width: 14px; + height: 14px; + border-radius: 7px; + border: 1px solid $secondary-content; + flex-shrink: 0; + + &::before { + background-color: $secondary-content; + content: ""; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + width: 7px; + height: 7px; + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + mask-image: url("$(res)/img/element-icons/cancel-rounded.svg"); + } + } + } + + .mx_ProgressBar { + width: auto; + margin-top: $spacing-8; + background: $background; + } + + &.mx_UserOnboardingButton_completed .mx_ProgressBar { + display: none; + } +} diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx index ab8620a26df3..e5eee9cff74f 100644 --- a/src/components/structures/LeftPanel.tsx +++ b/src/components/structures/LeftPanel.tsx @@ -45,9 +45,12 @@ import { shouldShowComponent } from "../../customisations/helpers/UIComponents"; import { UIComponent } from "../../settings/UIFeature"; import { ButtonEvent } from "../views/elements/AccessibleButton"; import PosthogTrackers from "../../PosthogTrackers"; +import PageType from "../../PageTypes"; +import { UserOnboardingButton } from "../views/user-onboarding/UserOnboardingButton"; interface IProps { isMinimized: boolean; + pageType: PageType; resizeNotifier: ResizeNotifier; } @@ -390,6 +393,10 @@ export default class LeftPanel extends React.Component { onVisibilityChange={this.refreshStickyHeaders} /> ) } +
{ data-collapsed={this.props.collapseLhs ? true : undefined} > diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx index 06883703bdf3..2702392d3ff7 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx @@ -42,6 +42,7 @@ interface IState { export default class PreferencesUserSettingsTab extends React.Component { static ROOM_LIST_SETTINGS = [ 'breadcrumbs', + "FTUE.userOnboardingButton", ]; static SPACES_SETTINGS = [ diff --git a/src/components/views/user-onboarding/UserOnboardingButton.tsx b/src/components/views/user-onboarding/UserOnboardingButton.tsx new file mode 100644 index 000000000000..3e7d25e40c20 --- /dev/null +++ b/src/components/views/user-onboarding/UserOnboardingButton.tsx @@ -0,0 +1,87 @@ +/* +Copyright 2022 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 classNames from "classnames"; +import React, { useCallback } from "react"; + +import { Action } from "../../../dispatcher/actions"; +import defaultDispatcher from "../../../dispatcher/dispatcher"; +import { useSettingValue } from "../../../hooks/useSettings"; +import { useUserOnboardingTasks } from "../../../hooks/useUserOnboardingTasks"; +import { _t } from "../../../languageHandler"; +import { SettingLevel } from "../../../settings/SettingLevel"; +import SettingsStore from "../../../settings/SettingsStore"; +import AccessibleButton from "../../views/elements/AccessibleButton"; +import ProgressBar from "../../views/elements/ProgressBar"; +import Heading from "../../views/typography/Heading"; + +function toPercentage(progress: number): string { + return (progress * 100).toFixed(0); +} + +interface Props { + selected: boolean; + minimized: boolean; +} + +export function UserOnboardingButton({ selected, minimized }: Props) { + const [completedTasks, waitingTasks] = useUserOnboardingTasks(); + + const completed = completedTasks.length; + const waiting = waitingTasks.length; + const total = completed + waiting; + + const progress = waiting ? completed / total : 1; + + const onDismiss = useCallback(() => { + SettingsStore.setValue("FTUE.userOnboardingButton", null, SettingLevel.ACCOUNT, false); + }, []); + + const visible = useSettingValue("FTUE.userOnboardingButton"); + if (!visible || minimized) { + return null; + } + + return ( + defaultDispatcher.fire(Action.ViewHomePage)}> + { !minimized && ( + <> +
+ + { _t("Welcome") } + + { !completed && ( +
+ { toPercentage(progress) }% +
+ ) } + +
+ + + ) } +
+ ); +} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 6d25730f4abf..bf7ee69ac6d1 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -951,6 +951,7 @@ "Order rooms by name": "Order rooms by name", "Show rooms with unread notifications first": "Show rooms with unread notifications first", "Show shortcuts to recently viewed rooms above the room list": "Show shortcuts to recently viewed rooms above the room list", + "Show shortcut to welcome page above the room list": "Show shortcut to welcome page above the room list", "Show hidden events in timeline": "Show hidden events in timeline", "Low bandwidth mode (requires compatible homeserver)": "Low bandwidth mode (requires compatible homeserver)", "Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)": "Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)", @@ -1147,6 +1148,7 @@ "Anchor": "Anchor", "Headphones": "Headphones", "Folder": "Folder", + "Welcome": "Welcome", "Secure messaging for friends and family.": "Secure messaging for friends and family.", "With free end-to-end encrypted messaging, and unlimited voice and video calls, Element is a great way to stay in touch.": "With free end-to-end encrypted messaging, and unlimited voice and video calls, Element is a great way to stay in touch.", "Secure messaging for work.": "Secure messaging for work.", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 44d82da5cd47..773b4a79f060 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -804,6 +804,11 @@ export const SETTINGS: {[setting: string]: ISetting} = { default: true, controller: new IncompatibleController("feature_breadcrumbs_v2", true), }, + "FTUE.userOnboardingButton": { + supportedLevels: LEVELS_ACCOUNT_SETTINGS, + displayName: _td("Show shortcut to welcome page above the room list"), + default: true, + }, "showHiddenEventsInTimeline": { displayName: _td("Show hidden events in timeline"), supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,