mirror of
https://github.com/urbit/shrub.git
synced 2024-12-19 16:51:42 +03:00
interface: inject hooks to track position of tutorial elements
This commit is contained in:
parent
44debd2936
commit
1e7a09714b
@ -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;
|
||||
|
@ -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<ChatInput>();
|
||||
|
||||
|
@ -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<HTMLElement>(null);
|
||||
const isTutorialGroup = path === '/ship/~hastuc-dibtux/beginner-island';
|
||||
useTutorialModal(
|
||||
'start',
|
||||
isTutorialGroup,
|
||||
anchorRef.current
|
||||
);
|
||||
return (
|
||||
<Tile to={`/~landscape${path}`} gridColumnStart={first ? '1' : null}>
|
||||
<Tile ref={anchorRef} position="relative" bg={isTutorialGroup ? 'lightBlue' : undefined} to={`/~landscape${path}`} gridColumnStart={first ? '1' : null}>
|
||||
<Col height="100%" justifyContent="space-between">
|
||||
<Text>{title}</Text>
|
||||
<Col>
|
||||
|
@ -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 = (
|
||||
<Box p={typeof p === 'undefined' ? 2 : p} width="100%" height="100%">
|
||||
{props.children}
|
||||
</Box>
|
||||
);
|
||||
|
||||
if (to) {
|
||||
if (routeList.indexOf(to) !== -1 || to === '/~profile' || to.startsWith('/~landscape/')) {
|
||||
childElement= (<Link to={to}>{childElement}</Link>);
|
||||
} else {
|
||||
childElement= (<a href={to}>{childElement}</a>);
|
||||
}
|
||||
let childElement = (
|
||||
<Box p={typeof p === 'undefined' ? 2 : p} width="100%" height="100%">
|
||||
{props.children}
|
||||
</Box>
|
||||
);
|
||||
|
||||
if (to) {
|
||||
if (routeList.indexOf(to) !== -1 || to === '/~profile' || to.startsWith('/~landscape/')) {
|
||||
childElement= (<Link to={to}>{childElement}</Link>);
|
||||
} else {
|
||||
childElement= (<a href={to}>{childElement}</a>);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<SquareBox
|
||||
borderRadius={2}
|
||||
overflow="hidden"
|
||||
bg={bg || "white"}
|
||||
color={props?.color || 'washedGray'}
|
||||
boxShadow={boxShadow || '0 0 0px 1px inset'}
|
||||
style={{ gridColumnStart }}
|
||||
>
|
||||
<Box
|
||||
{...props}
|
||||
height="100%"
|
||||
width="100%"
|
||||
>
|
||||
{childElement}
|
||||
</Box>
|
||||
</SquareBox>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<SquareBox
|
||||
ref={ref}
|
||||
position="relative"
|
||||
borderRadius={2}
|
||||
overflow="hidden"
|
||||
bg={bg || "white"}
|
||||
color={props?.color || 'washedGray'}
|
||||
boxShadow={boxShadow || '0 0 0px 1px inset'}
|
||||
style={{ gridColumnStart }}
|
||||
>
|
||||
<Box
|
||||
{...rest}
|
||||
height="100%"
|
||||
width="100%"
|
||||
>
|
||||
{childElement}
|
||||
</Box>
|
||||
</SquareBox>
|
||||
);
|
||||
});
|
||||
|
||||
export default Tile;
|
||||
|
@ -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) {
|
||||
? <BaseImage src={contact.avatar} width='100%' height='100%' style={{ objectFit: 'cover' }} />
|
||||
: <Sigil ship={ship} size={96} color={hexColor} />;
|
||||
|
||||
const anchorRef = useRef<HTMLElement | null>(null);
|
||||
|
||||
useTutorialModal('profile', ship === `~${window.ship}`, anchorRef.current);
|
||||
|
||||
return (
|
||||
<Center
|
||||
p={4}
|
||||
@ -55,7 +60,7 @@ export function Profile(props: any) {
|
||||
<SetStatus ship={ship} contact={contact} api={props.api} />
|
||||
) : null
|
||||
}
|
||||
<Row width="100%" height="300px">
|
||||
<Row ref={anchorRef} width="100%" height="300px">
|
||||
{cover}
|
||||
</Row>
|
||||
<Row
|
||||
|
@ -11,9 +11,7 @@ import { Box, Col } from "@tlon/indigo-react";
|
||||
import { useOutsideClick } from "~/logic/lib/useOutsideClick";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { Portal } from "./Portal";
|
||||
|
||||
type AlignY = "top" | "bottom";
|
||||
type AlignX = "left" | "right";
|
||||
import { getRelativePosition, AlignY, AlignX } from "~/logic/lib/relativePosition";
|
||||
|
||||
interface DropdownProps {
|
||||
children: ReactNode;
|
||||
@ -44,46 +42,11 @@ export function Dropdown(props: DropdownProps) {
|
||||
const [coords, setCoords] = useState({});
|
||||
|
||||
const updatePos = useCallback(() => {
|
||||
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) {
|
||||
|
@ -21,12 +21,12 @@ interface HoverBoxLinkProps {
|
||||
to: string;
|
||||
}
|
||||
|
||||
export const HoverBoxLink = ({
|
||||
export const HoverBoxLink = React.forwardRef(({
|
||||
to,
|
||||
children,
|
||||
...rest
|
||||
}: HoverBoxLinkProps & PropFunc<typeof HoverBox>) => (
|
||||
<Link to={to}>
|
||||
}: HoverBoxLinkProps & PropFunc<typeof HoverBox>, ref) => (
|
||||
<Link ref={ref} to={to}>
|
||||
<HoverBox {...rest}>{children}</HoverBox>
|
||||
</Link>
|
||||
);
|
||||
));
|
||||
|
@ -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' }} />
|
||||
) : <Sigil ship={ship} size={16} color={color} icon />;
|
||||
|
||||
const anchorRef = useRef(null);
|
||||
|
||||
useTutorialModal('leap', true, anchorRef.current);
|
||||
|
||||
return (
|
||||
<Box
|
||||
display='grid'
|
||||
@ -64,7 +70,7 @@ const StatusBar = (props) => {
|
||||
</Box>
|
||||
)}
|
||||
<Icon icon='LeapArrow'/>
|
||||
<Text ml={2} color='black'>
|
||||
<Text ref={anchorRef} ml={2} color='black'>
|
||||
Leap
|
||||
</Text>
|
||||
<Text display={['none', 'inline']} ml={2} color='gray'>
|
||||
|
@ -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<HTMLElement | null>(null)
|
||||
|
||||
useTutorialModal('notifications', true, anchorRef.current);
|
||||
|
||||
return (
|
||||
<Col mb="6" gapY="4" flexShrink={0}>
|
||||
<Text id="notifications" fontSize="2" fontWeight="bold">
|
||||
<Text ref={anchorRef} id="notifications" fontSize="2" fontWeight="bold">
|
||||
Channel Notifications
|
||||
</Text>
|
||||
<BaseLabel display="flex" cursor="pointer">
|
||||
|
@ -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<HTMLElement | null>(null);
|
||||
useTutorialModal(
|
||||
"group-desc",
|
||||
resource === "/ship/~hastuc-dibtux/beginner-island",
|
||||
anchorRef.current
|
||||
);
|
||||
return (
|
||||
<Col maxWidth="300px" gapY="4">
|
||||
<Col ref={anchorRef} maxWidth="300px" gapY="4">
|
||||
<Row gapX="2">
|
||||
<MetadataIcon
|
||||
borderRadius="1"
|
||||
|
@ -199,6 +199,7 @@ export function GroupsPane(props: GroupsPaneProps) {
|
||||
memberCount={memberCount}
|
||||
channelCount={0}
|
||||
metadata={groupAssociation.metadata}
|
||||
resource={groupAssociation.group}
|
||||
/>
|
||||
} else {
|
||||
summary = (<Box p="4"><Text fontSize="0" color='gray'>
|
||||
|
@ -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<HTMLElement | null>(null);
|
||||
useTutorialModal('channels', true, anchorRef.current);
|
||||
|
||||
return (
|
||||
<ScrollbarLessCol
|
||||
ref={anchorRef}
|
||||
display={display}
|
||||
width="100%"
|
||||
gridRow="1/2"
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React, {useRef} from "react";
|
||||
import _ from 'lodash';
|
||||
|
||||
import { Icon, Row, Box, Text, BaseImage } from "@tlon/indigo-react";
|
||||
@ -9,6 +9,7 @@ import { Groups, Association } from "~/types";
|
||||
import { Sigil } from '~/logic/lib/sigil';
|
||||
import urbitOb from 'urbit-ob';
|
||||
import { getModuleIcon, getItemTitle, uxToHex } from "~/logic/lib/util";
|
||||
import {useTutorialModal} from "~/views/components/useTutorialModal";
|
||||
|
||||
function SidebarItemIndicator(props: { status?: SidebarItemStatus }) {
|
||||
switch (props.status) {
|
||||
@ -41,6 +42,12 @@ export function SidebarItem(props: {
|
||||
const mod = association?.metadata?.module || appName;
|
||||
const rid = association?.resource
|
||||
const groupPath = association?.group;
|
||||
const anchorRef = useRef<HTMLElement | null>(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 (
|
||||
<HoverBoxLink
|
||||
ref={anchorRef}
|
||||
to={to}
|
||||
bg="white"
|
||||
bgActive="washedGray"
|
||||
|
Loading…
Reference in New Issue
Block a user