From 1e7a09714b6e0de92e95fe8ac2dbc8192a1db736 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Mon, 8 Feb 2021 10:36:06 +1000 Subject: [PATCH] interface: inject hooks to track position of tutorial elements --- .../src/logic/reducers/contact-update.ts | 1 - .../src/views/apps/chat/ChatResource.tsx | 1 - .../views/apps/launch/components/Groups.tsx | 12 +++- .../apps/launch/components/tiles/tile.js | 72 ++++++++++--------- .../views/apps/profile/components/Profile.tsx | 9 ++- .../src/views/components/Dropdown.tsx | 45 ++---------- .../src/views/components/HoverBox.tsx | 8 +-- .../src/views/components/StatusBar.js | 10 ++- .../ChannelPopoverRoutes/Notifications.tsx | 9 ++- .../landscape/components/GroupSummary.tsx | 14 +++- .../views/landscape/components/GroupsPane.tsx | 1 + .../landscape/components/Sidebar/Sidebar.tsx | 7 +- .../components/Sidebar/SidebarItem.tsx | 10 ++- 13 files changed, 104 insertions(+), 95 deletions(-) diff --git a/pkg/interface/src/logic/reducers/contact-update.ts b/pkg/interface/src/logic/reducers/contact-update.ts index 7dd519d08a..44cbc6cfb0 100644 --- a/pkg/interface/src/logic/reducers/contact-update.ts +++ b/pkg/interface/src/logic/reducers/contact-update.ts @@ -55,7 +55,6 @@ const edit = (json: ContactUpdate, state: S) => { data && (ship in state.contacts) ) { - console.log(data); const [field] = Object.keys(data['edit-field']); if (!field) { return; diff --git a/pkg/interface/src/views/apps/chat/ChatResource.tsx b/pkg/interface/src/views/apps/chat/ChatResource.tsx index 667cc6022b..34c512f7c6 100644 --- a/pkg/interface/src/views/apps/chat/ChatResource.tsx +++ b/pkg/interface/src/views/apps/chat/ChatResource.tsx @@ -36,7 +36,6 @@ export function ChatResource(props: ChatResourceProps) { const [,, owner, name] = station.split('/'); const ourContact = contacts?.[`~${window.ship}`]; - console.log(contacts); const chatInput = useRef(); diff --git a/pkg/interface/src/views/apps/launch/components/Groups.tsx b/pkg/interface/src/views/apps/launch/components/Groups.tsx index 8a23536d2c..43f9d54eb7 100644 --- a/pkg/interface/src/views/apps/launch/components/Groups.tsx +++ b/pkg/interface/src/views/apps/launch/components/Groups.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, {useRef} from "react"; import { Box, Text, Col } from "@tlon/indigo-react"; import f from "lodash/fp"; import _ from "lodash"; @@ -7,6 +7,7 @@ import { Associations, Association, Unreads, UnreadStats } from "~/types"; import { alphabeticalOrder } from "~/logic/lib/util"; import { getUnreadCount, getNotificationCount } from "~/logic/lib/hark"; import Tile from "../components/tiles/tile"; +import { useTutorialModal } from "~/views/components/useTutorialModal"; interface GroupsProps { associations: Associations; @@ -73,8 +74,15 @@ interface GroupProps { } function Group(props: GroupProps) { const { path, title, unreads, updates, first = false } = props; + const anchorRef = useRef(null); + const isTutorialGroup = path === '/ship/~hastuc-dibtux/beginner-island'; + useTutorialModal( + 'start', + isTutorialGroup, + anchorRef.current + ); return ( - + {title} diff --git a/pkg/interface/src/views/apps/launch/components/tiles/tile.js b/pkg/interface/src/views/apps/launch/components/tiles/tile.js index a065c91214..5eef6717ed 100644 --- a/pkg/interface/src/views/apps/launch/components/tiles/tile.js +++ b/pkg/interface/src/views/apps/launch/components/tiles/tile.js @@ -22,43 +22,45 @@ const SquareBox = styled(Box)` `; const routeList = defaultApps.map(a => `/~${a}`); -export default class Tile extends React.Component { - render() { - const { bg, to, href, p, boxShadow, gridColumnStart, ...props } = this.props; +const Tile = React.forwardRef((props, ref) => { + const { bg, to, href, p, boxShadow, gridColumnStart, ...rest } = props; - let childElement = ( - - {props.children} - - ); - - if (to) { - if (routeList.indexOf(to) !== -1 || to === '/~profile' || to.startsWith('/~landscape/')) { - childElement= ({childElement}); - } else { - childElement= ({childElement}); - } + let childElement = ( + + {props.children} + + ); + if (to) { + if (routeList.indexOf(to) !== -1 || to === '/~profile' || to.startsWith('/~landscape/')) { + childElement= ({childElement}); + } else { + childElement= ({childElement}); } - - return ( - - - {childElement} - - - ); } -} + + + return ( + + + {childElement} + + + ); +}); + +export default Tile; diff --git a/pkg/interface/src/views/apps/profile/components/Profile.tsx b/pkg/interface/src/views/apps/profile/components/Profile.tsx index a5fc37c183..6f06f3277d 100644 --- a/pkg/interface/src/views/apps/profile/components/Profile.tsx +++ b/pkg/interface/src/views/apps/profile/components/Profile.tsx @@ -1,4 +1,4 @@ -import React, {useEffect} from "react"; +import React, {useEffect, useRef} from "react"; import { Sigil } from "~/logic/lib/sigil"; import { ViewProfile } from './ViewProfile'; import { EditProfile } from './EditProfile'; @@ -15,6 +15,7 @@ import { } from "@tlon/indigo-react"; import useLocalState from "~/logic/state/local"; import { useHistory } from "react-router-dom"; +import {useTutorialModal} from "~/views/components/useTutorialModal"; export function Profile(props: any) { @@ -43,6 +44,10 @@ export function Profile(props: any) { ? : ; + const anchorRef = useRef(null); + + useTutorialModal('profile', ship === `~${window.ship}`, anchorRef.current); + return (
) : null } - + {cover} { - const rect = anchorRef.current?.getBoundingClientRect(); - if (rect) { - const bounds = { - top: rect.top, - left: rect.left, - bottom: document.documentElement.clientHeight - rect.bottom, - right: document.documentElement.clientWidth - rect.right, - }; - const alignX = _.isArray(props.alignX) ? props.alignX : [props.alignX]; - const alignY = _.isArray(props.alignY) ? props.alignY : [props.alignY]; - - let newCoords = { - ..._.reduce( - alignX, - (acc, a, idx) => ({ - ...acc, - [a]: _.zipWith( - [...Array(idx), `${bounds[a]}px`], - acc[a] || [], - (a, b) => a || b || null - ), - }), - {} - ), - ..._.reduce( - alignY, - (acc, a, idx) => ({ - ...acc, - [a]: _.zipWith( - [...Array(idx), `${bounds[a]}px`], - acc[a] || [], - (a, b) => a || b || null - ), - }), - {} - ), - }; + const newCoords = getRelativePosition(anchorRef.current, props.alignX, props.alignY); + if(newCoords) { setCoords(newCoords); } - }, [setCoords, anchorRef.current]); + }, [setCoords, anchorRef.current, props.alignY, props.alignX]); useEffect(() => { if (!open) { diff --git a/pkg/interface/src/views/components/HoverBox.tsx b/pkg/interface/src/views/components/HoverBox.tsx index 5b2959eafd..d678c1e4d2 100644 --- a/pkg/interface/src/views/components/HoverBox.tsx +++ b/pkg/interface/src/views/components/HoverBox.tsx @@ -21,12 +21,12 @@ interface HoverBoxLinkProps { to: string; } -export const HoverBoxLink = ({ +export const HoverBoxLink = React.forwardRef(({ to, children, ...rest -}: HoverBoxLinkProps & PropFunc) => ( - +}: HoverBoxLinkProps & PropFunc, ref) => ( + {children} -); +)); diff --git a/pkg/interface/src/views/components/StatusBar.js b/pkg/interface/src/views/components/StatusBar.js index 06835cfd04..ce15d38544 100644 --- a/pkg/interface/src/views/components/StatusBar.js +++ b/pkg/interface/src/views/components/StatusBar.js @@ -1,6 +1,7 @@ import React, { useState, - useEffect + useEffect, + useRef } from 'react'; import { @@ -18,6 +19,7 @@ import { StatusBarItem } from './StatusBarItem'; import { Sigil } from '~/logic/lib/sigil'; import { uxToHex } from "~/logic/lib/util"; import { SetStatusBarModal } from './SetStatusBarModal'; +import { useTutorialModal } from './useTutorialModal'; import useLocalState from '~/logic/state/local'; @@ -43,6 +45,10 @@ const StatusBar = (props) => { style={{ objectFit: 'cover' }} /> ) : ; + const anchorRef = useRef(null); + + useTutorialModal('leap', true, anchorRef.current); + return ( { )} - + Leap diff --git a/pkg/interface/src/views/landscape/components/ChannelPopoverRoutes/Notifications.tsx b/pkg/interface/src/views/landscape/components/ChannelPopoverRoutes/Notifications.tsx index 2df198f024..5cebda2f70 100644 --- a/pkg/interface/src/views/landscape/components/ChannelPopoverRoutes/Notifications.tsx +++ b/pkg/interface/src/views/landscape/components/ChannelPopoverRoutes/Notifications.tsx @@ -1,8 +1,9 @@ -import React from "react"; +import React, {useRef} from "react"; import { Col, Text, BaseLabel, Label } from "@tlon/indigo-react"; import GlobalApi from "~/logic/api/global"; import { Association, NotificationGraphConfig } from "~/types"; import { StatelessAsyncToggle } from "~/views/components/StatelessAsyncToggle"; +import {useTutorialModal} from "~/views/components/useTutorialModal"; interface ChannelNotificationsProps { api: GlobalApi; @@ -24,9 +25,13 @@ export function ChannelNotifications(props: ChannelNotificationsProps) { await api.hark[func](rid, "/"); }; + const anchorRef = useRef(null) + + useTutorialModal('notifications', true, anchorRef.current); + return ( - + Channel Notifications diff --git a/pkg/interface/src/views/landscape/components/GroupSummary.tsx b/pkg/interface/src/views/landscape/components/GroupSummary.tsx index 06b3ecc510..08543d2810 100644 --- a/pkg/interface/src/views/landscape/components/GroupSummary.tsx +++ b/pkg/interface/src/views/landscape/components/GroupSummary.tsx @@ -1,19 +1,27 @@ -import React, { ReactNode } from "react"; +import React, { ReactNode, useRef } from "react"; import { Metadata } from "~/types"; import { Col, Row, Text } from "@tlon/indigo-react"; import { MetadataIcon } from "./MetadataIcon"; +import { useTutorialModal } from "~/views/components/useTutorialModal"; interface GroupSummaryProps { metadata: Metadata; memberCount: number; channelCount: number; + resource?: string; children?: ReactNode; } export function GroupSummary(props: GroupSummaryProps) { - const { channelCount, memberCount, metadata, children } = props; + const { channelCount, memberCount, metadata, resource, children } = props; + const anchorRef = useRef(null); + useTutorialModal( + "group-desc", + resource === "/ship/~hastuc-dibtux/beginner-island", + anchorRef.current + ); return ( - + } else { summary = ( diff --git a/pkg/interface/src/views/landscape/components/Sidebar/Sidebar.tsx b/pkg/interface/src/views/landscape/components/Sidebar/Sidebar.tsx index 8998d4b928..7cd0e2dcb2 100644 --- a/pkg/interface/src/views/landscape/components/Sidebar/Sidebar.tsx +++ b/pkg/interface/src/views/landscape/components/Sidebar/Sidebar.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode } from 'react'; +import React, { ReactNode, useRef } from 'react'; import styled from 'styled-components'; import { Col @@ -19,6 +19,7 @@ import { getGroupFromWorkspace } from '~/logic/lib/workspace'; import { SidebarAppConfigs } from './types'; import { SidebarList } from './SidebarList'; import { roleForShip } from '~/logic/lib/group'; +import {useTutorialModal} from '~/views/components/useTutorialModal'; const ScrollbarLessCol = styled(Col)` scrollbar-width: none !important; @@ -64,8 +65,12 @@ export function Sidebar(props: SidebarProps) { const role = props.groups?.[groupPath] ? roleForShip(props.groups[groupPath], window.ship) : undefined; const isAdmin = (role === 'admin') || (workspace?.type === 'home'); + const anchorRef = useRef(null); + useTutorialModal('channels', true, anchorRef.current); + return ( (null) + useTutorialModal( + mod as any, + groupPath === '/ship/~hastuc-dibtux/beginner-island', + anchorRef.current + ); const app = apps[appName]; const isUnmanaged = groups?.[groupPath]?.hidden || false; if (!app) { @@ -87,6 +94,7 @@ export function SidebarItem(props: { return (