diff --git a/res/css/_components.scss b/res/css/_components.scss index 4a712d33b44..4338cac6957 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -273,6 +273,7 @@ @import "./views/rooms/_Stickers.scss"; @import "./views/rooms/_ThreadSummary.scss"; @import "./views/rooms/_TopUnreadMessagesBar.scss"; +@import "./views/rooms/_UserOnboardingElement.scss"; @import "./views/rooms/_VideoRoomSummary.scss"; @import "./views/rooms/_VoiceRecordComposerTile.scss"; @import "./views/rooms/_WhoIsTypingTile.scss"; diff --git a/res/css/views/rooms/_UserOnboardingElement.scss b/res/css/views/rooms/_UserOnboardingElement.scss new file mode 100644 index 00000000000..f477f58f69f --- /dev/null +++ b/res/css/views/rooms/_UserOnboardingElement.scss @@ -0,0 +1,64 @@ +.mx_UserOnboardingElement { + display: flex; + flex-direction: column; + align-content: stretch; + align-items: stretch; + border-radius: 8px; + margin: 8px 8px 0; + padding: 12px; + gap: 8px; + + &.mx_UserOnboardingElement_selected, + &:hover, + &:focus-within { + background-color: $panel-actions; + } + + .mx_UserOnboardingElement_content { + display: flex; + flex-direction: row; + gap: 5px; + align-items: center; + + .mx_Heading_h4 { + margin-right: auto; + font-size: 14px; + color: $primary-content; + } + + .mx_UserOnboardingElement_percentage { + font-size: 1.2rem; + color: $secondary-content; + } + + .mx_UserOnboardingElement_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; + background: $background; + } +} diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx index ab8620a26df..74de2037fc6 100644 --- a/src/components/structures/LeftPanel.tsx +++ b/src/components/structures/LeftPanel.tsx @@ -24,6 +24,7 @@ import RoomList from "../views/rooms/RoomList"; import CallHandler from "../../CallHandler"; import { HEADER_HEIGHT } from "../views/rooms/RoomSublist"; import { Action } from "../../dispatcher/actions"; +import { UserOnboardingElement } from "../views/rooms/UserOnboardingElement"; import RoomSearch from "./RoomSearch"; import ResizeNotifier from "../../utils/ResizeNotifier"; import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; @@ -45,9 +46,11 @@ 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"; 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/rooms/UserOnboardingElement.tsx b/src/components/views/rooms/UserOnboardingElement.tsx new file mode 100644 index 00000000000..2009c199f33 --- /dev/null +++ b/src/components/views/rooms/UserOnboardingElement.tsx @@ -0,0 +1,83 @@ +/* +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 { _t } from "../../../languageHandler"; +import { SettingLevel } from "../../../settings/SettingLevel"; +import SettingsStore from "../../../settings/SettingsStore"; +import AccessibleButton from "../elements/AccessibleButton"; +import ProgressBar from "../elements/ProgressBar"; +import Heading from "../typography/Heading"; + +function toPercentage(progress: number): string { + return (progress * 100).toFixed(0); +} + +interface Props { + selected: boolean; + minimized: boolean; +} + +export function UserOnboardingElement({ selected, minimized }: Props) { + const [completedTasks, tasks] = [0, 0]; + const progress = tasks ? completedTasks / tasks : 1; + const completed = !tasks || tasks === completedTasks; + + 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) }% +
+ ) } + +
+ { !completed && ( + + ) } + + ) } +
+ ); +} diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx index 06883703bdf..2702392d3ff 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/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index ad82fd4318e..06a30550420 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -950,6 +950,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)", @@ -1907,6 +1908,7 @@ "Open thread": "Open thread", "Jump to first unread message.": "Jump to first unread message.", "Mark all as read": "Mark all as read", + "Welcome": "Welcome", "Video": "Video", "Joining…": "Joining…", "Joined": "Joined", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index d783c19db32..32fdb3b682f 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -793,6 +793,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,