Merge pull request #4872 from urbit/tbcs/typescript-cleanup

more typescript cleanup
This commit is contained in:
matildepark 2021-05-10 20:27:58 -04:00 committed by GitHub
commit 181f6652ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
152 changed files with 1144 additions and 985 deletions

View File

@ -1,4 +1,5 @@
import { Content, Enc, GraphNode, GroupPolicy, Path, Patp, Post, Resource } from '@urbit/api';
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
import _ from 'lodash';
import { decToUd, deSig, resourceAsPath, unixToDa } from '~/logic/lib/util';
import { makeResource, resourceFromPath } from '../lib/group';
@ -9,7 +10,7 @@ export const createBlankNodeWithChildPost = (
parentIndex = '',
childIndex = '',
contents: Content[]
) => {
): GraphNode => {
const date = unixToDa(Date.now()).toString();
const nodeIndex = parentIndex + '/' + date;
@ -35,7 +36,7 @@ export const createBlankNodeWithChildPost = (
hash: null,
signatures: []
},
children: childGraph
children: childGraph as BigIntOrderedMap<GraphNode>
};
};

View File

@ -1,5 +1,6 @@
import { IndexedNotification, NotificationGraphConfig, Unreads } from '@urbit/api';
import bigInt, { BigInteger } from 'big-integer';
import _ from 'lodash';
import f from 'lodash/fp';
export function getLastSeen(
@ -31,7 +32,7 @@ export function getNotificationCount(
): number {
const unread = unreads.graph?.[path] || {};
return Object.keys(unread)
.map(index => unread[index]?.notifications?.length || 0)
.map(index => _.get(unread[index], 'notifications.length', 0))
.reduce(f.add, 0);
}

View File

@ -20,11 +20,12 @@ function getPermalinkForAssociatedGroup(group: string) {
type Permalink = GraphPermalink | GroupPermalink;
interface GroupPermalink {
export interface GroupPermalink {
type: 'group';
group: string;
link: string;
}
export interface GraphPermalink {
type: 'graph';
link: string;

View File

@ -1,9 +1,9 @@
import { Box } from '@tlon/indigo-react';
import React, {
ReactNode,
useCallback,
useMemo,
useRef, useState
ReactNode,
useCallback,
useMemo,
useRef, useState
} from 'react';
import { PropFunc } from '~/types';
import { ModalOverlay } from '~/views/components/ModalOverlay';
@ -57,7 +57,7 @@ export function useModal(props: UseModalProps & PropFunc<typeof Box>): UseModalR
display="flex"
alignItems="stretch"
flexDirection="column"
spacing="2"
spacing={2}
dismiss={dismiss}
{...rest}
>

View File

@ -5,7 +5,7 @@ import bigInt, { BigInteger } from 'big-integer';
import { enableMapSet } from 'immer';
import _ from 'lodash';
import f from 'lodash/fp';
import { useCallback, useEffect, useMemo, useState } from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { IconRef } from '~/types';
import useSettingsState from '../state/settings';
@ -423,6 +423,13 @@ export const useHovering = (): useHoveringInterface => {
return useMemo(() => ({ hovering, bind }), [hovering, bind]);
};
export function withHovering<T>(Component: React.ComponentType<T>) {
return React.forwardRef((props, ref) => {
const { hovering, bind } = useHovering();
return <Component ref={ref} hovering={hovering} bind={bind} {...props} />
})
}
const DM_REGEX = /ship\/~([a-z]|-)*\/dm--/;
export function getItemTitle(association: Association): string {
if (DM_REGEX.test(association.resource)) {

View File

@ -19,12 +19,14 @@ const withStateo = <
});
};
const withState = <
StateType extends BaseState<StateType>,
stateKey extends keyof StateType
>(
interface StatePicker extends Array<any> {
0: UseStore<any>;
1?: string[];
}
const withState = (
Component: any,
stores: ([UseStore<StateType>, stateKey[]])[]
stores: StatePicker[]
) => {
return React.forwardRef((props, ref) => {
const stateProps: unknown = {};

View File

@ -1,3 +1,4 @@
import { GraphNode } from '@urbit/api';
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
import bigInt, { BigInteger } from 'big-integer';
import produce from 'immer';
@ -52,14 +53,14 @@ const keys = (json, state: GraphState): GraphState => {
const processNode = (node) => {
// is empty
if (!node.children) {
return produce(node, (draft) => {
return produce<GraphNode>(node, (draft: GraphNode) => {
draft.children = new BigIntOrderedMap();
});
}
// is graph
return produce(node, (draft) => {
draft.children = new BigIntOrderedMap()
return produce<GraphNode>(node, (draft: GraphNode) => {
draft.children = new BigIntOrderedMap<GraphNode>()
.gas(_.map(draft.children, (item, idx) =>
[bigInt(idx), processNode(item)] as [BigInteger, any]
));

View File

@ -64,11 +64,19 @@ function calculateCount(json: any, state: HarkState) {
let count = 0;
_.forEach(state.unreads.graph, (graphs) => {
_.forEach(graphs, (graph) => {
count += (graph?.notifications || []).length;
if (typeof graph?.notifications === 'object') {
count += graph?.notifications.length;
} else {
count += 0;
}
});
});
_.forEach(state.unreads.group, (group) => {
count += (group?.notifications || []).length;
if (typeof group?.notifications === 'object') {
count += group?.notifications.length;
} else {
count += 0;
}
});
state.notificationsCount = count;
return state;

View File

@ -44,13 +44,13 @@ export interface BaseState<StateType> extends State {
set: (fn: (state: StateType) => void) => void;
}
export const createState = <T extends {}>(
export const createState = <T extends BaseState<T>>(
name: string,
properties: T,
properties: { [K in keyof Omit<T, 'set'>]: T[K] },
blacklist: string[] = []
): UseStore<T & BaseState<T>> => create(persist((set, get) => ({
): UseStore<T> => create(persist((set, get) => ({
set: fn => stateSetter(fn, set),
...properties
...properties as any
}), {
blacklist,
name: stateStorageKey(name),

View File

@ -108,8 +108,18 @@ interface ChatEditorState {
message: string;
}
interface CodeMirrorShim {
setValue: (string) => void;
setOption: (option: string, property: any) => void;
focus: () => void;
execCommand: (string) => void;
getValue: () => string;
getInputField: () => HTMLInputElement;
element: HTMLElement;
}
export default class ChatEditor extends Component<ChatEditorProps, ChatEditorState> {
editor: ProxyHandler<unknown> | null;
editor: CodeMirrorShim;
constructor(props: ChatEditorProps) {
super(props);
@ -222,7 +232,7 @@ export default class ChatEditor extends Component<ChatEditorProps, ChatEditorSta
<Row
backgroundColor='white'
alignItems='center'
flexGrow='1'
flexGrow={1}
height='100%'
paddingTop={MOBILE_BROWSER_REGEX.test(navigator.userAgent) ? '16px' : '0'}
paddingBottom={MOBILE_BROWSER_REGEX.test(navigator.userAgent) ? '16px' : '0'}
@ -235,7 +245,7 @@ export default class ChatEditor extends Component<ChatEditorProps, ChatEditorSta
{MOBILE_BROWSER_REGEX.test(navigator.userAgent)
? <MobileBox
data-value={this.state.message}
fontSize="1"
fontSize={1}
lineHeight="tall"
onClick={(event) => {
if (this.editor) {
@ -245,7 +255,7 @@ export default class ChatEditor extends Component<ChatEditorProps, ChatEditorSta
>
<BaseTextArea
fontFamily={inCodeMode ? 'Source Code Pro' : 'Inter'}
fontSize="1"
fontSize={1}
lineHeight="tall"
rows={1}
style={{ width: '100%', background: 'transparent', color: 'currentColor' }}
@ -254,7 +264,7 @@ export default class ChatEditor extends Component<ChatEditorProps, ChatEditorSta
this.messageChange(null, null, event.target.value)
}
onKeyDown={event =>
this.messageChange(null, null, event.target.value)
this.messageChange(null, null, (event.target as any).value)
}
ref={(input) => {
if (!input)

View File

@ -29,7 +29,7 @@ interface ChatInputState {
currentInput: string;
}
class ChatInput extends Component<ChatInputProps, ChatInputState> {
export class ChatInput extends Component<ChatInputProps, ChatInputState> {
private chatEditor: React.RefObject<ChatEditor>;
constructor(props) {

View File

@ -1,9 +1,10 @@
/* eslint-disable max-lines-per-function */
import { BaseImage, Box, Col, Icon, Row, Rule, Text } from '@tlon/indigo-react';
import { Contact, Post } from '@urbit/api';
import { Contact, MentionContent, Post } from '@urbit/api';
import bigInt from 'big-integer';
import moment from 'moment';
import React, {
Ref,
useEffect,
useMemo, useState
} from 'react';
@ -20,13 +21,13 @@ import useLocalState from '~/logic/state/local';
import useSettingsState, { selectCalmState } from '~/logic/state/settings';
import { Dropdown } from '~/views/components/Dropdown';
import ProfileOverlay from '~/views/components/ProfileOverlay';
import { GraphContent} from '~/views/landscape/components/Graph/GraphContent';
import { GraphContent } from '~/views/landscape/components/Graph/GraphContent';
export const DATESTAMP_FORMAT = '[~]YYYY.M.D';
interface DayBreakProps {
when: string;
when: string | number;
shimTop?: boolean;
}
@ -55,7 +56,7 @@ export const DayBreak = ({ when, shimTop = false }: DayBreakProps) => (
);
export const UnreadMarker = React.forwardRef(
({ dismissUnread }: any, ref) => {
({ dismissUnread }: any, ref: Ref<HTMLDivElement>) => {
const [visible, setVisible] = useState(false);
const idling = useIdlingState();
@ -113,7 +114,7 @@ const MessageActionItem = (props) => {
);
};
const MessageActions = ({ api, onReply, onDelete, association, msg, isAdmin, permalink }) => {
const MessageActions = ({ onReply, onDelete, msg, isAdmin, permalink }) => {
const isOwn = () => msg.author === window.ship;
const { doCopy, copyDisplay } = useCopy(permalink, 'Copy Message Link');
@ -205,14 +206,14 @@ interface ChatMessageProps {
msg: Post;
previousMsg?: Post;
nextMsg?: Post;
isLastRead: boolean;
permalink: string;
isLastRead?: boolean;
permalink?: string;
transcluded?: number;
className?: string;
isPending: boolean;
isPending?: boolean;
style?: unknown;
isLastMessage?: boolean;
dismissUnread: () => void;
dismissUnread?: () => void;
api: GlobalApi;
highlighted?: boolean;
renderSigil?: boolean;
@ -220,27 +221,24 @@ interface ChatMessageProps {
innerRef: (el: HTMLDivElement | null) => void;
onReply?: (msg: Post) => void;
showOurContact: boolean;
onDelete?: () => void;
}
function ChatMessage(props: ChatMessageProps) {
let { highlighted } = props;
const {
msg,
previousMsg,
nextMsg,
isLastRead,
group,
association,
isLastRead = false,
className = '',
isPending,
isPending = false,
style,
isLastMessage,
api,
showOurContact,
fontSize,
hideHover,
dismissUnread,
permalink
dismissUnread = () => null,
permalink = ''
} = props;
if (typeof msg === 'string' || !msg) {
@ -257,7 +255,7 @@ function ChatMessage(props: ChatMessageProps) {
msg.number === 1
);
const ourMention = msg?.contents?.some((e) => {
const ourMention = msg?.contents?.some((e: MentionContent) => {
return e?.mention && e?.mention === window.ship;
});
@ -291,12 +289,10 @@ function ChatMessage(props: ChatMessageProps) {
const messageProps = {
msg,
timestamp,
association,
isPending,
showOurContact,
api,
highlighted,
fontSize,
hideHover,
transcluded,
onReply,
@ -494,7 +490,7 @@ export const Message = React.memo(({
position='absolute'
width='36px'
textAlign='right'
left='0'
left={0}
top='2px'
lineHeight="tall"
fontSize={0}
@ -528,10 +524,10 @@ export const MessagePlaceholder = ({
}) => (
<Box
width='100%'
fontSize='2'
pl='3'
pt='4'
pr='3'
fontSize={2}
pl={3}
pt={4}
pr={3}
display='flex'
lineHeight='tall'
className={className}
@ -539,7 +535,7 @@ export const MessagePlaceholder = ({
{...props}
>
<Box
pr='3'
pr={3}
verticalAlign='top'
backgroundColor='white'
style={{ float: 'left' }}
@ -562,20 +558,20 @@ export const MessagePlaceholder = ({
>
<Box
className='hide-child'
paddingTop='4'
paddingTop={4}
style={{ visibility: index % 5 == 0 ? 'initial' : 'hidden' }}
>
<Text
display='inline-block'
verticalAlign='middle'
fontSize='0'
fontSize={0}
color='washedGray'
cursor='default'
>
<Text maxWidth='32rem' display='block'>
<Text
backgroundColor='washedGray'
borderRadius='2'
borderRadius={2}
display='block'
width='100%'
height='100%'
@ -586,12 +582,12 @@ export const MessagePlaceholder = ({
display='inline-block'
mono
verticalAlign='middle'
fontSize='0'
washedGray
fontSize={0}
color='washedGray'
>
<Text
background='washedGray'
borderRadius='2'
borderRadius={2}
display='block'
height='1em'
style={{ width: `${((index % 3) + 1) * 3}em` }}
@ -600,16 +596,16 @@ export const MessagePlaceholder = ({
<Text
mono
verticalAlign='middle'
fontSize='0'
ml='2'
washedGray
borderRadius='2'
fontSize={0}
ml={2}
color='washedGray'
borderRadius={2}
display={['none', 'inline-block']}
className='child'
>
<Text
backgroundColor='washedGray'
borderRadius='2'
borderRadius={2}
display='block'
width='100%'
height='100%'
@ -619,7 +615,7 @@ export const MessagePlaceholder = ({
<Text
display='block'
backgroundColor='washedGray'
borderRadius='2'
borderRadius={2}
height='1em'
style={{ width: `${(index % 5) * 20}%` }}
></Text>

View File

@ -11,7 +11,7 @@ import useGraphState from '~/logic/state/graph';
import ShareProfile from '~/views/apps/chat/components/ShareProfile';
import { Loading } from '~/views/components/Loading';
import SubmitDragger from '~/views/components/SubmitDragger';
import ChatInput from './ChatInput';
import ChatInput, { ChatInput as NakedChatInput } from './ChatInput';
import ChatWindow from './ChatWindow';
interface ChatPaneProps {
@ -82,14 +82,14 @@ export function ChatPane(props: ChatPaneProps): ReactElement {
} = props;
const graphTimesentMap = useGraphState(state => state.graphTimesentMap);
const ourContact = useOurContact();
const chatInput = useRef<ChatInput>();
const chatInput = useRef<NakedChatInput>();
const onFileDrag = useCallback(
(files: FileList | File[]) => {
if (!chatInput.current) {
return;
}
chatInput.current?.uploadFiles(files);
(chatInput.current as NakedChatInput)?.uploadFiles(files);
},
[chatInput.current]
);

View File

@ -16,7 +16,7 @@ type ChatWindowProps = {
unreadCount: number;
graph: Graph;
graphSize: number;
station: unknown;
station?: unknown;
fetchMessages: (newer: boolean) => Promise<boolean>;
api: GlobalApi;
scrollTo?: BigInteger;
@ -36,6 +36,11 @@ interface ChatWindowState {
unreadIndex: BigInteger;
}
interface RendererProps {
index: bigInt.BigInteger;
scrollWindow: any;
}
const virtScrollerStyle = { height: '100%' };
class ChatWindow extends Component<
@ -99,11 +104,12 @@ class ChatWindow extends Component<
});
}
dismissedInitialUnread(): void {
dismissedInitialUnread(): boolean {
const { unreadCount, graph } = this.props;
return this.state.unreadIndex.eq(bigInt.zero) ? unreadCount > graph.size :
this.state.unreadIndex.neq(graph.keys()?.[unreadCount]?.[0] ?? bigInt.zero);
return this.state.unreadIndex.eq(bigInt.zero)
? unreadCount > graph.size
: this.state.unreadIndex.neq(graph.keys()?.[unreadCount]?.[0] ?? bigInt.zero);
}
handleWindowBlur(): void {
@ -173,7 +179,7 @@ class ChatWindow extends Component<
}
}
renderer = React.forwardRef(({ index, scrollWindow }, ref) => {
renderer = React.forwardRef(({ index, scrollWindow }: RendererProps, ref) => {
const {
api,
showOurContact,

View File

@ -22,16 +22,16 @@ const UnreadNotice = (props): ReactElement | null => {
className='unread-notice'
>
<Center>
<Box backgroundColor='white' borderRadius='3' overflow='hidden'>
<Box backgroundColor='white' borderRadius={3} overflow='hidden'>
<Box
backgroundColor='washedBlue'
display='flex'
alignItems='center'
p='2'
fontSize='0'
p={2}
fontSize={0}
justifyContent='space-between'
borderRadius='3'
border='1'
borderRadius={3}
border={1}
borderColor='lightBlue'
>
<Text

View File

@ -1,4 +1,5 @@
import { Center, Text } from '@tlon/indigo-react';
import { GraphConfig } from '@urbit/api';
import React, { ReactElement } from 'react';
import { Route, Switch, useHistory } from 'react-router-dom';
import GlobalApi from '~/logic/api/global';
@ -40,8 +41,8 @@ const GraphApp = (props: GraphAppProps): ReactElement => {
if(!graphKeys.has(resource)) {
autoJoin();
} else if(Boolean(association) && 'graph' in association.config) {
history.push(`/~landscape/home/resource/${association.metadata.config.graph}${path}`);
} else if(Boolean(association) && 'graph' in association.metadata.config) {
history.push(`/~landscape/home/resource/${(association.metadata.config as GraphConfig).graph}${path}`);
}
return (
<Center width="100%" height="100%">

View File

@ -6,13 +6,13 @@ import { Helmet } from 'react-helmet';
import styled from 'styled-components';
import GlobalApi from '~/logic/api/global';
import {
hasTutorialGroup,
hasTutorialGroup,
TUTORIAL_BOOK,
TUTORIAL_CHAT, TUTORIAL_GROUP,
TUTORIAL_HOST,
TUTORIAL_BOOK,
TUTORIAL_CHAT, TUTORIAL_GROUP,
TUTORIAL_HOST,
TUTORIAL_LINKS
TUTORIAL_LINKS
} from '~/logic/lib/tutorialModal';
import { useModal } from '~/logic/lib/useModal';
import { useQuery } from '~/logic/lib/useQuery';
@ -67,8 +67,8 @@ export const LaunchApp = (props: LaunchAppProps): ReactElement | null => {
const hashBox = (
<Box
position={['relative', 'absolute']}
left="0"
bottom="0"
left={0}
bottom={0}
backgroundColor="white"
ml={3}
mb={3}
@ -120,28 +120,28 @@ export const LaunchApp = (props: LaunchAppProps): ReactElement | null => {
dismiss();
};
return exitingTut ? (
<Col maxWidth="350px" p="3">
<Col maxWidth="350px" p={3}>
<Icon icon="Info" fill="black"></Icon>
<Text my="3" lineHeight="tall">
<Text my={3} lineHeight="tall">
You can always restart the tutorial by typing &ldquo;tutorial&rdquo; in Leap
</Text>
<Row gapX="2" justifyContent="flex-end">
<Row gapX={2} justifyContent="flex-end">
<Button primary onClick={onDismiss}>Ok</Button>
</Row>
</Col>
) : (
<Col maxWidth="350px" p="3">
<Col maxWidth="350px" p={3}>
<Box position="absolute" left="-16px" top="-16px">
<StarIcon width="32px" height="32px" color="blue" display="block" />
</Box>
<Text mb="3" lineHeight="tall" fontWeight="medium">Welcome</Text>
<Text mb="3" lineHeight="tall">
<Text mb={3} lineHeight="tall" fontWeight="medium">Welcome</Text>
<Text mb={3} lineHeight="tall">
You have been invited to use Landscape, an interface to chat
and interact with communities
<br />
Would you like a tour of Landscape?
</Text>
<Row gapX="2" justifyContent="flex-end">
<Row gapX={2} justifyContent="flex-end">
<Button
backgroundColor="washedGray"
onClick={() => setExitingTut(true)}
@ -181,7 +181,7 @@ export const LaunchApp = (props: LaunchAppProps): ReactElement | null => {
<ScrollbarLessBox height='100%' overflowY='scroll' display="flex" flexDirection="column">
{modal}
<Box
mx='2'
mx={2}
display='grid'
gridTemplateColumns='repeat(auto-fill, minmax(128px, 1fr))'
gridGap={3}
@ -208,7 +208,7 @@ export const LaunchApp = (props: LaunchAppProps): ReactElement | null => {
color="black"
icon="Home"
/>
<Text ml="2" mt='1px' color="black">My Channels</Text>
<Text ml={2} mt='1px' color="black">My Channels</Text>
</Row>
</Box>
</Tile>

View File

@ -47,8 +47,8 @@ export default function Groups(props: GroupsProps & Parameters<typeof Box>[0]) {
const groups = Object.values(associations?.groups || {})
.filter(e => e?.group in groupState)
.sort(sortGroupsAlph);
const graphUnreads = getGraphUnreads(associations || {}, unreads);
const graphNotifications = getGraphNotifications(associations || {}, unreads);
const graphUnreads = getGraphUnreads(associations || {} as Associations, unreads);
const graphNotifications = getGraphNotifications(associations || {} as Associations, unreads);
return (
<>
@ -82,7 +82,7 @@ interface GroupProps {
const selectJoined = (s: SettingsState) => s.tutorial.joined;
function Group(props: GroupProps) {
const { path, title, unreads, updates, first = false } = props;
const anchorRef = useRef<HTMLElement>(null);
const anchorRef = useRef<HTMLDivElement>(null);
const isTutorialGroup = path === `/ship/${TUTORIAL_HOST}/${TUTORIAL_GROUP}`;
useTutorialModal(
'start',
@ -104,7 +104,7 @@ function Group(props: GroupProps) {
(<Text>{days} day{days !== 1 && 's'} remaining</Text>)
}
{updates > 0 &&
(<Text mt="1" color="blue">{updates} update{updates !== 1 && 's'} </Text>)
(<Text mt={1} color="blue">{updates} update{updates !== 1 && 's'} </Text>)
}
{unreads > 0 &&
(<Text color="lightGray">{unreads}</Text>)

View File

@ -1,17 +1,18 @@
import React, { ReactElement } from 'react';
import GlobalApi from '~/logic/api/global';
import useLaunchState from '~/logic/state/launch';
import { WeatherState } from '~/types';
import BasicTile from './tiles/basic';
import ClockTile from './tiles/clock';
import CustomTile from './tiles/custom';
import WeatherTile from './tiles/weather';
interface TileProps {
export interface TileProps {
api: GlobalApi;
}
const Tiles = (props: TileProps): ReactElement => {
const weather = useLaunchState(state => state.weather);
const weather = useLaunchState(state => state.weather) as WeatherState;
const tileOrdering = useLaunchState(state => state.tileOrdering);
const tileState = useLaunchState(state => state.tiles);
const tiles = tileOrdering.filter((key) => {
@ -26,7 +27,6 @@ const Tiles = (props: TileProps): ReactElement => {
<BasicTile
key={key}
title={basic.title}
iconUrl={basic.iconUrl}
linkedUrl={basic.linkedUrl}
/>
);

View File

@ -21,7 +21,7 @@ const BasicTile = (props: BasicTileProps): ReactElement => (
display='inline-block'
verticalAlign='top'
mt='5px'
mr='2'
mr={2}
/>
: null
}{props.title}

View File

@ -120,7 +120,11 @@ const SvgArc = ({ start, end, ...rest }) => {
return <path d={d} {...rest} />;
};
class ClockText extends React.Component<ClockTextProps, ClockTextState> {
interface ClockTextState {
time: number;
}
class ClockText extends React.Component<{}, ClockTextState> {
interval?: NodeJS.Timeout;
constructor(props) {
super(props);
@ -176,7 +180,34 @@ class ClockText extends React.Component<ClockTextProps, ClockTextState> {
}
}
class Clock extends React.PureComponent {
interface ClockProps {
data: {
latitude?: number;
longitude?: number;
}
}
interface ClockState {
time: number;
lat: number;
lon: number;
geolocationSuccess: boolean;
sunrise: number;
sunsetStart: number;
sunset: number;
sunriseEnd: number;
dusk: number;
dawn: number;
night: number;
nightEnd: number;
nauticalDawn: number;
nauticalDusk: number;
}
class Clock extends React.PureComponent<ClockProps, ClockState> {
angle: number;
referenceTime: moment.Moment;
interval: NodeJS.Timeout;
constructor(props) {
super(props);
this.angle = 0;
@ -188,7 +219,7 @@ class Clock extends React.PureComponent {
geolocationSuccess: false,
sunrise: 0,
sunsetStart: 0,
sunset:0,
sunset: 0,
sunriseEnd: 0,
dusk: 0,
dawn: 0,

View File

@ -13,7 +13,7 @@ export default class CustomTile extends React.PureComponent {
backgroundColor='white'
border='1px solid'
borderColor='lightGray'
borderRadius='2'
borderRadius={2}
>
<BaseImage
position='absolute'

View File

@ -1,7 +1,8 @@
import { Box } from '@tlon/indigo-react';
import React from 'react';
import { Box, BoxProps } from '@tlon/indigo-react';
import React, { RefObject } from 'react';
import { Link } from 'react-router-dom';
import styled from 'styled-components';
import { PaddingProps } from 'styled-system';
import defaultApps from '~/logic/lib/default-apps';
const SquareBox = styled(Box)`
@ -20,7 +21,17 @@ const SquareBox = styled(Box)`
`;
const routeList = defaultApps.map(a => `/~${a}`);
const Tile = React.forwardRef((props, ref) => {
type TileProps = BoxProps & {
bg?: string;
to?: string;
href?: string;
p?: PaddingProps;
children: any;
gridColumnStart?: number;
color?: string;
}
const Tile = React.forwardRef((props: TileProps, ref: RefObject<HTMLDivElement>) => {
const { bg, to, href, p, boxShadow, gridColumnStart, ...rest } = props;
let childElement = (

View File

@ -1,6 +1,7 @@
import { BaseInput, Box, Icon, Text } from '@tlon/indigo-react';
import moment from 'moment';
import React from 'react';
import GlobalApi from '~/logic/api/global';
import withState from '~/logic/lib/withState';
import useLaunchState from '~/logic/state/launch';
import ErrorBoundary from '~/views/components/ErrorBoundary';
@ -36,8 +37,20 @@ const imperialCountries = [
'Liberia',
];
class WeatherTile extends React.Component {
constructor(props) {
interface WeatherTileProps {
weather: any;
api: GlobalApi;
location: string;
}
interface WeatherTileState {
location: string;
manualEntry: boolean;
error: boolean;
}
class WeatherTile extends React.Component<WeatherTileProps, WeatherTileState> {
constructor(props: WeatherTileProps) {
super(props);
this.state = {
location: '',
@ -50,11 +63,7 @@ class WeatherTile extends React.Component {
locationSubmit() {
navigator.geolocation.getCurrentPosition((res) => {
const location = `${res.coords.latitude},${res.coords.longitude}`;
this.setState({
location
}, (err) => {
console.log(err);
}, { maximumAge: Infinity, timeout: 10000 });
this.setState({ location });
this.props.api.launch.weather(location);
this.setState({ manualEntry: !this.state.manualEntry });
});
@ -62,10 +71,8 @@ class WeatherTile extends React.Component {
manualLocationSubmit(event) {
event.preventDefault();
const location = document.getElementById('location').value;
this.setState({ location }, (err) => {
console.log(err);
}, { maximumAge: Infinity, timeout: 10000 });
const location = (document.getElementById('location') as HTMLInputElement).value;
this.setState({ location });
this.props.api.launch.weather(location);
this.setState({ manualEntry: !this.state.manualEntry });
}
@ -91,7 +98,7 @@ class WeatherTile extends React.Component {
let secureCheck;
let error;
if (this.state.error === true) {
error = <Text display='block' color='red' pt='1'>Please try again.</Text>;
error = <Text display='block' color='red' pt={1}>Please try again.</Text>;
}
if (location.protocol === 'https:') {
secureCheck = (
@ -128,15 +135,15 @@ class WeatherTile extends React.Component {
{locationName ? ` Current location is near ${locationName}.` : ''}
</Text>
{error}
<Box mt='auto' display='flex' marginBlockEnd='0'>
<Box mt='auto' display='flex' marginBlockEnd={0}>
<BaseInput
id="location"
size="10"
size={10}
width='100%'
color='black'
fontSize='0'
fontSize={0}
backgroundColor='transparent'
border='0'
border={0}
type="text"
autoFocus
placeholder="GPS, ZIP, City"
@ -150,10 +157,10 @@ class WeatherTile extends React.Component {
backgroundColor='transparent'
color='black'
cursor='pointer'
flexShrink='0'
pl='1'
fontSize='0'
border='0'
flexShrink={0}
pl={1}
fontSize={0}
border={0}
type="submit"
onClick={this.manualLocationSubmit.bind(this)}
value="->"
@ -173,7 +180,7 @@ class WeatherTile extends React.Component {
onClick={() => this.setState({ manualEntry: !this.state.manualEntry })}
>
<Box>
<Icon icon='Weather' display='inline-block' verticalAlign='top' mt='3px' mr='2' />
<Icon icon='Weather' display='inline-block' verticalAlign='top' mt='3px' mr={2} />
<Text>Weather</Text>
</Box>
<Text style={{ cursor: 'pointer' }}>
@ -219,7 +226,7 @@ class WeatherTile extends React.Component {
title={`${locationName} Weather`}
>
<Text>
<Icon icon='Weather' display='inline' mr='2' style={{ position: 'relative', top: '.3em' }} />
<Icon icon='Weather' display='inline' mr={2} style={{ position: 'relative', top: '.3em' }} />
<Text
cursor='pointer'
onClick={() =>
@ -269,7 +276,7 @@ class WeatherTile extends React.Component {
flexDirection="column"
justifyContent="flex-start"
>
<Text><Icon icon='Weather' color='black' display='inline' mr='2' style={{ position: 'relative', top: '.3em' }} /> Weather</Text>
<Text><Icon icon='Weather' color='black' display='inline' mr={2} style={{ position: 'relative', top: '.3em' }} /> Weather</Text>
<Text width='100%' display='flex' flexDirection='column' mt={1}>
Loading, please check again later...
</Text>

View File

@ -2,7 +2,7 @@ import { Box, Col, Text } from '@tlon/indigo-react';
import { Association, Graph, Group } from '@urbit/api';
import bigInt from 'big-integer';
import React, {
Component
Component, ReactNode
} from 'react';
import GlobalApi from '~/logic/api/global';
import { isWriter } from '~/logic/lib/group';
@ -31,6 +31,11 @@ const style = {
alignItems: 'center'
};
interface RendererProps {
index: BigInteger;
children?: ReactNode;
}
class LinkWindow extends Component<LinkWindowProps, {}> {
fetchLinks = async () => true;
@ -39,7 +44,7 @@ class LinkWindow extends Component<LinkWindowProps, {}> {
return isWriter(group, association.resource);
}
renderItem = React.forwardRef<HTMLDivElement>(({ index, scrollWindow }, ref) => {
renderItem = React.forwardRef<HTMLDivElement>(({ index }: RendererProps, ref) => {
const { props } = this;
const { association, graph, api } = props;
const [, , ship, name] = association.resource.split('/');
@ -60,7 +65,7 @@ class LinkWindow extends Component<LinkWindowProps, {}> {
ref={ref}
key={index.toString()}
mx="auto"
mt="4"
mt={4}
maxWidth="768px"
width="100%"
flexShrink={0}
@ -96,7 +101,7 @@ class LinkWindow extends Component<LinkWindowProps, {}> {
<Col
key={0}
mx="auto"
mt="4"
mt={4}
maxWidth="768px"
width="100%"
flexShrink={0}

View File

@ -1,6 +1,6 @@
import { Action, Anchor, Box, Col, Icon, Row, Rule, Text } from '@tlon/indigo-react';
import { Association, GraphNode, Group } from '@urbit/api';
import React, { ReactElement, useCallback, useEffect, useRef } from 'react';
import { Association, GraphNode, Group, TextContent, UrlContent } from '@urbit/api';
import React, { ReactElement, RefObject, useCallback, useEffect, useRef } from 'react';
import { Link, Redirect } from 'react-router-dom';
import GlobalApi from '~/logic/api/global';
import { roleForShip } from '~/logic/lib/group';
@ -15,8 +15,13 @@ import { PermalinkEmbed } from '../../permalinks/embed';
interface LinkItemProps {
node: GraphNode;
association: Association;
resource: string; api: GlobalApi; group: Group; path: string; }
export const LinkItem = React.forwardRef((props: LinkItemProps, ref): ReactElement => {
resource: string;
api: GlobalApi;
group: Group;
path: string;
baseUrl: string;
}
export const LinkItem = React.forwardRef((props: LinkItemProps, ref: RefObject<HTMLDivElement>): ReactElement => {
const {
association,
node,
@ -61,7 +66,7 @@ export const LinkItem = React.forwardRef((props: LinkItemProps, ref): ReactEleme
const author = node.post.author;
const size = node.children ? node.children.size : 0;
const contents = node.post.contents;
const contents = node.post.contents as [TextContent, UrlContent];
const hostname = URLparser.exec(contents[1].url) ? URLparser.exec(contents[1].url)[4] : null;
const href = URLparser.exec(contents[1].url) ? contents[1].url : `http://${contents[1].url}`;
@ -130,8 +135,8 @@ export const LinkItem = React.forwardRef((props: LinkItemProps, ref): ReactEleme
<>
<RemoteContent
ref={(r) => {
remoteRef.current = r;
}}
remoteRef.current = r;
}}
renderUrl={false}
url={href}
text={contents[0].text}
@ -166,14 +171,14 @@ export const LinkItem = React.forwardRef((props: LinkItemProps, ref): ReactEleme
</>
)}
</Box>
<Row minWidth='0' flexShrink={0} width="100%" justifyContent="space-between" py={3} bg="white">
<Row minWidth={0} flexShrink={0} width="100%" justifyContent="space-between" py={3} bg="white">
<Author
showImage
isRelativeTime
ship={author}
date={node.post['time-sent']}
group={group}
lineHeight="1"
lineHeight={1}
/>
<Box ml="auto">
<Link
@ -208,7 +213,7 @@ export const LinkItem = React.forwardRef((props: LinkItemProps, ref): ReactEleme
</Col>
}
>
<Icon ml="2" display="block" icon="Ellipsis" color="gray" />
<Icon ml={2} display="block" icon="Ellipsis" color="gray" />
</Dropdown>
</Row>

View File

@ -1,5 +1,5 @@
import { Anchor, Box, Col, Icon, Row, Text } from '@tlon/indigo-react';
import { Association, Group, Post } from '@urbit/api';
import { Association, GraphNotificationContents, GraphNotifIndex, Post } from '@urbit/api';
import { BigInteger } from 'big-integer';
import _ from 'lodash';
import React, { useCallback } from 'react';
@ -15,9 +15,6 @@ import {
useAssocForGraph,
useAssocForGroup
} from '~/logic/state/metadata';
import {
GraphNotificationContents, GraphNotifIndex
} from '~/types';
import Author from '~/views/components/Author';
import { GraphContent } from '~/views/landscape/components/Graph/GraphContent';
import { PermalinkEmbed } from '../permalinks/embed';
@ -84,9 +81,9 @@ const GraphUrl = ({ contents, api }) => {
);
}
return (
<Box borderRadius="2" p="2" bg="scales.black05">
<Box borderRadius={2} p={2} bg="scales.black05">
<Anchor underline={false} target="_blank" color="black" href={link.url}>
<Icon verticalAlign="bottom" mr="2" icon="ArrowExternal" />
<Icon verticalAlign="bottom" mr={2} icon="ArrowExternal" />
{text}
</Anchor>
</Box>
@ -97,17 +94,17 @@ function ContentSummary({ icon, name, author, to }) {
return (
<Link to={to}>
<Col
gapY="1"
gapY={1}
flexDirection={['column', 'row']}
alignItems={['flex-start', 'center']}
>
<Row
alignItems="center"
gapX="2"
p="1"
gapX={2}
p={1}
width="fit-content"
borderRadius="2"
border="1"
borderRadius={2}
border={1}
borderColor="lightGray"
>
<Icon display="block" icon={icon} />
@ -116,7 +113,7 @@ function ContentSummary({ icon, name, author, to }) {
</Text>
</Row>
<Row ml={[0, 1]} alignItems="center">
<Text lineHeight="1" fontWeight="medium" mr="1">
<Text lineHeight={1} fontWeight="medium" mr={1}>
by
</Text>
<Author
@ -193,11 +190,7 @@ interface PostsByAuthor {
}
const GraphNodes = (props: {
posts: Post[];
graph: string;
hideAuthors?: boolean;
group?: Group;
groupPath: string;
description: string;
index: string;
mod: string;
association: Association;
@ -208,7 +201,6 @@ const GraphNodes = (props: {
mod,
hidden,
index,
description,
hideAuthors = false,
association
} = props;
@ -242,7 +234,7 @@ const GraphNodes = (props: {
date={time}
/>
)}
<Col gapY="2" py={hideAuthors ? 0 : 2} width="100%">
<Col gapY={2} py={hideAuthors ? 0 : 2} width="100%">
{_.map(posts, post => (
<GraphNodeContent
key={post.index}
@ -328,18 +320,17 @@ export function GraphNotification(props: {
groupTitle={groupTitle}
content
/>
<Col onClick={onClick} gapY="2" flexGrow={1} width="100%" gridArea="main">
<Col onClick={onClick} gapY={2} flexGrow={1} width="100%" gridArea="main">
<GraphNodes
hideAuthors={hideAuthors}
posts={contents.slice(0, 4)}
mod={index.module}
description={index.description}
index={contents?.[0].index}
association={association}
hidden={groups[association?.group]?.hidden}
/>
{contents.length > 4 && (
<Text mb="2" gray>
<Text mb={2} gray>
+ {contents.length - 4} more
</Text>
)}

View File

@ -4,6 +4,7 @@ import {
GroupNotifIndex,
GroupUpdate
} from '@urbit/api';
import bigInt from 'big-integer';
import _ from 'lodash';
import React, { ReactElement } from 'react';
import GlobalApi from '~/logic/api/global';
@ -37,7 +38,7 @@ interface GroupNotificationProps {
archived: boolean;
read: boolean;
time: number;
timebox: BigInteger;
timebox: bigInt.BigInteger;
api: GlobalApi;
}

View File

@ -32,7 +32,7 @@ export function Header(
return (
<Row
flexDirection={['column-reverse', 'row']}
minHeight="4"
minHeight={4}
mb={content ? 2 : 0}
onClick={props.onClick}
flexWrap="wrap"
@ -40,7 +40,7 @@ export function Header(
gridArea="header"
overflow="hidden"
>
<Row gapX="1" overflow="hidden" alignItems="center">
<Row gapX={1} overflow="hidden" alignItems="center">
{authors.length > 0 && (
<>
<Author
@ -58,15 +58,15 @@ export function Header(
</>
)}
<Box whiteSpace="nowrap" overflow="hidden" textOverflow="ellipsis">
<Text lineHeight="tall" mr="1">
<Text lineHeight="tall" mr={1}>
{description} {channelTitle}
</Text>
</Box>
</Row>
<Row ml={[0, 1]} mb={[1, 0]} gapX="1" alignItems="center">
<Row ml={[0, 1]} mb={[1, 0]} gapX={1} alignItems="center">
{groupTitle && (
<>
<Text lineHeight="tall" fontSize="1" gray>
<Text lineHeight="tall" fontSize={1} gray>
{groupTitle}
</Text>
<Dot color="gray" />
@ -75,7 +75,7 @@ export function Header(
{time && (
<Timestamp
lineHeight="tall"
fontSize="1"
fontSize={1}
relative
stamp={moment(time)}
color="gray"

View File

@ -1,10 +1,10 @@
import { Box, Center, Col, LoadingSpinner, Text } from '@tlon/indigo-react';
import {
IndexedNotification,
IndexedNotification,
JoinRequests, Notifications,
JoinRequests, Notifications,
Timebox
Timebox
} from '@urbit/api';
import { BigInteger } from 'big-integer';
import _ from 'lodash';
@ -113,7 +113,7 @@ export default function Inbox(props: {
);
return (
<Col p="1" ref={scrollRef} position="relative" height="100%" overflowY="auto" overflowX="hidden">
<Col p={1} ref={scrollRef} position="relative" height="100%" overflowY="auto" overflowX="hidden">
<Invites pendingJoin={props.pendingJoin} api={api} />
{[...notificationsByDayMap.keys()].sort().reverse().map((day, index) => {
const timeboxes = notificationsByDayMap.get(day)!;
@ -129,15 +129,15 @@ export default function Inbox(props: {
);
})}
{isDone ? (
<Center mt="2" borderTop={notifications.length !== 0 ? 1 : 0} borderTopColor="lightGray" width="100%" height="96px">
<Text gray fontSize="1">No more notifications</Text>
<Center mt={2} borderTop={notifications.length !== 0 ? 1 : 0} borderTopColor="lightGray" width="100%" height="96px">
<Text gray fontSize={1}>No more notifications</Text>
</Center>
) : isLoading ? (
<Center mt="2" borderTop={notifications.length !== 0 ? 1 : 0} borderTopColor="lightGray" width="100%" height="96px">
<Center mt={2} borderTop={notifications.length !== 0 ? 1 : 0} borderTopColor="lightGray" width="100%" height="96px">
<LoadingSpinner />
</Center>
) : (
<Box mt="2" height="96px" />
<Box mt={2} height="96px" />
)}
</Col>

View File

@ -1,8 +1,8 @@
import { Box, Row, SegmentedProgressBar, Text } from '@tlon/indigo-react';
import {
joinError, joinProgress,
joinError, joinProgress,
JoinRequest
JoinRequest
} from '@urbit/api';
import React, { useCallback } from 'react';
import GlobalApi from '~/logic/api/global';
@ -34,8 +34,8 @@ export function JoiningStatus(props: JoiningStatusProps) {
<Row
display={['flex-column', 'flex']}
alignItems="center"
px="4"
gapX="4"
px={4}
gapX={4}
>
<Box flexGrow={1} maxWidth="400px">
<SegmentedProgressBar current={current + 1} segments={3} />

View File

@ -1,13 +1,9 @@
import { Box } from '@tlon/indigo-react';
import { Metadata } from '@urbit/api';
import React from 'react';
import { Header } from './header';
import { MetadataBody, NotificationProps } from './types';
function getInvolvedUsers(body: MetadataBody) {
return [];
}
function getDescription(body: MetadataBody) {
function getDescription(body: { metadata: Metadata}) {
const b = body.metadata;
if ('new' in b) {
return 'created';
@ -24,12 +20,12 @@ function getDescription(body: MetadataBody) {
}
}
export function MetadataNotification(props: NotificationProps<'metadata'>) {
export function MetadataNotification(props: any) {
const { unread } = props;
const description = getDescription(unread.unreads[0].body);
return (
<Box p="2">
<Box p={2}>
<Header
authors={[]}
description={description}

View File

@ -22,7 +22,7 @@ import { SwipeMenu } from '~/views/components/SwipeMenu';
import { GraphNotification } from './graph';
import { GroupNotification } from './group';
interface NotificationProps {
export interface NotificationProps {
notification: IndexedNotification;
time: BigInteger;
api: GlobalApi;
@ -40,7 +40,7 @@ function getMuted(
if (!('graph' in notification.contents)) {
throw new Error();
}
const parent = getParentIndex(index.graph, notification.contents.graph);
const parent = getParentIndex(idxNotif.index.graph, notification.contents.graph);
return (
_.findIndex(
@ -102,7 +102,7 @@ export function NotificationWrapper(props: {
menuWidth={100}
disabled={!isMobile}
menu={
<Button onClick={onArchive} ml="2" height="100%" width="92px" primary destructive>
<Button onClick={onArchive} ml={2} height="100%" width="92px" primary destructive>
Remove
</Button>
}
@ -125,7 +125,7 @@ export function NotificationWrapper(props: {
{children}
<Row
alignItems="flex-start"
gapX="2"
gapX={2}
gridArea="actions"
justifyContent="flex-end"
opacity={[0, hovering ? 1 : 0]}
@ -147,7 +147,7 @@ export function NotificationWrapper(props: {
}
export function Notification(props: NotificationProps) {
const { notification, associations, archived } = props;
const { notification, archived } = props;
const { read, contents, time } = notification.notification;
const wrapperProps = {

View File

@ -23,7 +23,7 @@ const HeaderLink = React.forwardRef((
return (
<Link to={to}>
<Text ref={ref} px="2" {...textProps} gray={!active} />
<Text ref={ref} px={2} {...textProps} gray={!active} />
</Link>
);
});
@ -67,21 +67,21 @@ export default function NotificationsScreen(props: any): ReactElement {
<Body>
<Col overflowY="hidden" height="100%">
<Row
p="3"
p={3}
alignItems="center"
height="48px"
justifyContent="space-between"
width="100%"
borderBottom="1"
borderBottom={1}
borderBottomColor="lightGray"
>
<Text fontWeight="bold" fontSize="2" lineHeight="1" ref={anchorRef}>
<Text fontWeight="bold" fontSize={2} lineHeight={1} ref={anchorRef}>
Notifications
</Text>
<Row
justifyContent="space-between"
gapX="3"
gapX={3}
>
<StatelessAsyncAction
overflow="hidden"
@ -93,7 +93,7 @@ export default function NotificationsScreen(props: any): ReactElement {
</StatelessAsyncAction>
<Link to="/~settings#notifications">
<Box>
<Icon lineHeight="1" icon="Adjust" />
<Icon lineHeight={1} icon="Adjust" />
</Box>
</Link>
</Row>

View File

@ -1,5 +1,5 @@
import { Anchor, Box, Col, Icon, Row, Text } from '@tlon/indigo-react';
import { Association, GraphNode, Group, Post } from '@urbit/api';
import { Association, GraphConfig, GraphNode, Group, Post, ReferenceContent, TextContent, UrlContent } from '@urbit/api';
import bigInt from 'big-integer';
import React from 'react';
import GlobalApi from '~/logic/api/global';
@ -38,7 +38,7 @@ function TranscludedLinkNode(props: {
switch (idx.length) {
case 1:
const [{ text }, link] = node.post.contents;
const [{ text }, link] = node.post.contents as [TextContent, UrlContent | ReferenceContent];
if('reference' in link) {
const permalink = referenceToPermalink(link).link;
return <PermalinkEmbed transcluded={transcluded + 1} api={api} link={permalink} association={assoc} />;
@ -76,6 +76,7 @@ function TranscludedLinkNode(props: {
</Box>
</Box>
);
case 2:
return (
<TranscludedComment
@ -170,7 +171,7 @@ function TranscludedPublishNode(props: {
?.get(bigInt.one)
?.children?.peekLargest()?.[1]!;
return (
<Col color="black" gapY="2">
<Col color="black" gapY={2}>
<Author
pl='12px'
pt='12px'
@ -182,7 +183,7 @@ function TranscludedPublishNode(props: {
group={group}
/>
<Text pl='44px' fontSize="2" fontWeight="medium">
{post.post.contents[0]?.text}
{(post.post.contents[0] as TextContent)?.text}
</Text>
<Box pl="44px" pr='3'>
<NotePreviewContent
@ -267,7 +268,7 @@ export function TranscludedNode(props: {
api: GlobalApi;
showOurContact?: boolean;
}) {
const { node, showOurContact, assoc, transcluded } = props;
const { node, showOurContact, assoc, transcluded, api } = props;
const group = useGroupForAssoc(assoc)!;
if (
@ -287,23 +288,19 @@ export function TranscludedNode(props: {
);
}
switch (assoc.metadata.config.graph) {
switch ((assoc.metadata.config as GraphConfig).graph) {
case 'chat':
return (
<Row width="100%" flexShrink={0} flexGrow={1} flexWrap="wrap">
<ChatMessage
width="100%"
renderSigil
transcluded={transcluded + 1}
containerClass="items-top cf hide-child"
className="items-top cf hide-child"
association={assoc}
group={group}
groups={{}}
msg={node.post}
fontSize="0"
ml="0"
mr="0"
fontSize={0}
showOurContact={showOurContact}
api={api}
mt='0'
/>
</Row>

View File

@ -1,4 +1,4 @@
import { Association } from '@urbit/api';
import { Association, GraphConfig } from '@urbit/api';
import React, { useCallback } from 'react';
import {
Redirect, Route, Switch
@ -82,7 +82,7 @@ function GroupRoutes(props: { group: string; url: string }) {
return <Redirect
to={toQuery(
{ auto: 'y', redir: location.pathname },
`${groupUrl}/join/${association.metadata.config.graph}${path}`
`${groupUrl}/join/${(association.metadata.config as GraphConfig).graph}${path}`
)}
/>;
}

View File

@ -1,27 +1,25 @@
import React, { useCallback, useEffect, useState } from "react";
import { useHistory, useLocation, Link } from 'react-router-dom';
import {
BaseAnchor, Box,
Center, Col, Icon, Row, Text
} from "@tlon/indigo-react";
import { Association, GraphNode, resourceFromPath } from '@urbit/api';
import React, { useCallback, useEffect, useState } from "react";
import { useHistory, useLocation } from 'react-router-dom';
import GlobalApi from '~/logic/api/global';
import {
getPermalinkForGraph, GraphPermalink as IGraphPermalink, parsePermalink
} from '~/logic/lib/permalinks';
import {
Action,
Box,
Text,
BaseAnchor,
Row,
Icon,
Col,
Center
} from "@tlon/indigo-react";
import { GroupLink } from "~/views/components/GroupLink";
import { getModuleIcon } from "~/logic/lib/util";
import useMetadataState from "~/logic/state/metadata";
import { useVirtualResizeProp } from "~/logic/lib/virtualContext";
import useGraphState from "~/logic/state/graph";
import { GraphNodeContent } from "../notifications/graph";
import useMetadataState from "~/logic/state/metadata";
import { GroupLink } from "~/views/components/GroupLink";
import { TranscludedNode } from "./TranscludedNode";
import {useVirtualResizeProp} from "~/logic/lib/virtualContext";
function GroupPermalink(props: { group: string; api: GlobalApi }) {
const { group, api } = props;
@ -29,9 +27,9 @@ function GroupPermalink(props: { group: string; api: GlobalApi }) {
<GroupLink
resource={group}
api={api}
pl="2"
border="1"
borderRadius="2"
pl={2}
border={1}
borderRadius={2}
borderColor="lightGray"
/>
);
@ -112,7 +110,7 @@ function GraphPermalink(
maxWidth={full ? null : "500px"}
border={full ? null : "1"}
borderColor="lightGray"
borderRadius="2"
borderRadius={2}
cursor="pointer"
onClick={(e) => {
navigate(e);
@ -140,7 +138,7 @@ function GraphPermalink(
<PermalinkDetails
known
showTransclusion={showTransclusion}
icon={getModuleIcon(association.metadata.config.graph)}
icon={getModuleIcon((association.metadata.config as GraphConfig).graph as GraphModule)}
title={association.metadata.title}
permalink={permalink}
/>

View File

@ -1,4 +1,4 @@
import { Association, Group } from '@urbit/api';
import { Association, GraphConfig, Group } from '@urbit/api';
import _ from 'lodash';
import React from 'react';
import { Redirect, Route, Switch } from 'react-router-dom';
@ -8,7 +8,7 @@ export function getGraphPermalink(
group: Group,
index: string
) {
const mod = assoc.metadata.config.graph;
const mod = (assoc.metadata.config as GraphConfig).graph;
const groupPath = group.hidden
? '/~landscape/home'
: `/~landscape${assoc.group}`;

View File

@ -1,8 +1,8 @@
import {
Button, Col, ManagedCheckboxField as Checkbox, ManagedForm as Form,
ManagedTextInputField as Input,
Button, Col, ManagedCheckboxField as Checkbox, ManagedForm as Form,
ManagedTextInputField as Input,
Row, Text
Row, Text
} from '@tlon/indigo-react';
import { Formik } from 'formik';
import _ from 'lodash';
@ -18,9 +18,9 @@ import { ColorInput } from '~/views/components/ColorInput';
import GroupSearch from '~/views/components/GroupSearch';
import { ImageInput } from '~/views/components/ImageInput';
import {
ProfileControls, ProfileHeader,
ProfileControls, ProfileHeader,
ProfileImages, ProfileStatus
ProfileImages, ProfileStatus
} from './Profile';
const formSchema = Yup.object({
@ -61,7 +61,7 @@ export function ProfileHeaderImageEdit(props: any): ReactElement {
<ImageInput id='cover' marginTop='-8px' width='288px' />
) : (
<Row>
<Button mr='2' onClick={() => setEditCover(true)}>
<Button mr={2} onClick={() => setEditCover(true)}>
Replace Header
</Button>
<Button onClick={e => handleClear(e)}>
@ -148,16 +148,16 @@ export function EditProfile(props: any): ReactElement {
cursor='pointer'
fontWeight='500'
color='blue'
pl='0'
pr='0'
border='0'
pl={0}
pr={0}
border={0}
style={{ appearance: 'none', background: 'transparent' }}
>
Save Edits
</Button>
<Text
py='2'
ml='3'
py={2}
ml={3}
fontWeight='500'
cursor='pointer'
onClick={() => {

View File

@ -16,7 +16,7 @@ export function ProfileHeader(props: any): ReactElement {
<Box
border='1px solid'
borderColor='lightGray'
borderRadius='3'
borderRadius={3}
overflow='hidden'
marginBottom='calc(64px + 2rem)'
>
@ -27,7 +27,7 @@ export function ProfileHeader(props: any): ReactElement {
export function ProfileImages(props: any): ReactElement {
const { hideAvatars } = useSettingsState(selectCalmState);
const { contact, hideCover, ship } = { ...props };
const { contact, hideCover, ship } = props;
const hexColor = contact?.color ? `#${uxToHex(contact.color)}` : '#000000';
const anchorRef = useRef<HTMLDivElement>(null);
@ -76,7 +76,7 @@ export function ProfileImages(props: any): ReactElement {
<Box
height='128px'
width='128px'
borderRadius='3'
borderRadius={3}
overflow='hidden'
position='absolute'
left='50%'
@ -91,18 +91,18 @@ export function ProfileImages(props: any): ReactElement {
export function ProfileControls(props: any): ReactElement {
return (
<Row alignItems='center' justifyContent='space-between' px='3'>
<Row alignItems='center' justifyContent='space-between' px={3}>
{props.children}
</Row>
);
}
export function ProfileStatus(props: any): ReactElement {
const { contact } = { ...props };
const { contact } = props;
return (
<RichText
mb='0'
py='2'
mb={0}
py={2}
disableRemoteContent
maxWidth='18rem'
overflowX='hidden'
@ -120,14 +120,14 @@ export function ProfileStatus(props: any): ReactElement {
}
export function ProfileActions(props: any): ReactElement {
const { ship, isPublic, contact, api } = { ...props };
const { ship, isPublic, contact, api } = props;
const history = useHistory();
return (
<Row>
{ship === `~${window.ship}` ? (
<>
<Text
py='2'
py={2}
cursor='pointer'
fontWeight='500'
onClick={() => {
@ -145,8 +145,8 @@ export function ProfileActions(props: any): ReactElement {
</Text>
<SetStatusBarModal
isControl
py='2'
ml='3'
py={2}
ml={3}
api={api}
ship={`~${window.ship}`}
contact={contact}
@ -155,7 +155,7 @@ export function ProfileActions(props: any): ReactElement {
) : (
<>
<Text
py='2'
py={2}
cursor='pointer'
fontWeight='500'
onClick={() => history.push(`/~landscape/dm/${ship.substring(1)}`)}

View File

@ -45,15 +45,15 @@ export function ViewProfile(props: any): ReactElement {
</Text>
</Center>
</Row>
<Col pb={2} mt='3' alignItems='center' justifyContent='center' width='100%'>
<Col pb={2} mt={3} alignItems='center' justifyContent='center' width='100%'>
<Center flexDirection='column' maxWidth='32rem'>
<RichText width='100%' disableRemoteContent>
<RichText api={props.api} width='100%' disableRemoteContent>
{contact?.bio ? contact.bio : ''}
</RichText>
</Center>
</Col>
{(contact?.groups || []).length > 0 && (
<Col gapY='3' mb='3' mt='6' alignItems='flex-start'>
<Col gapY={3} mb={3} mt={6} alignItems='flex-start'>
<Text gray>Pinned Groups</Text>
<Col>
{contact?.groups.slice().sort(lengthOrder).map(g => (

View File

@ -36,7 +36,7 @@ export default function ProfileScreen(props: any) {
border={1}
borderColor='lightGray'
overflowY='auto'
flexGrow
flexGrow={1}
>
<Box>
<Profile

View File

@ -1,17 +1,18 @@
import { GraphNode } from '@urbit/api';
import bigInt from 'big-integer';
import { FormikHelpers } from 'formik';
import _ from 'lodash';
import React, { ReactElement } from 'react';
import { RouteComponentProps, useLocation } from 'react-router-dom';
import GlobalApi from '~/logic/api/global';
import { referenceToPermalink } from '~/logic/lib/permalinks';
import { editPost, getLatestRevision } from '~/logic/lib/publish';
import { useWaitForProps } from '~/logic/lib/useWaitForProps';
import { referenceToPermalink } from '~/logic/lib/permalinks';
import { PostForm, PostFormSchema } from './NoteForm';
interface EditPostProps {
ship: string;
noteId: number;
noteId: bigInt.BigInteger;
note: GraphNode;
api: GlobalApi;
book: string;

View File

@ -93,7 +93,6 @@ export function MarkdownEditor(
return (
<Box
height="100%"
position="relative"
className="publish"
p={1}
@ -111,10 +110,10 @@ export function MarkdownEditor(
value={value}
options={options}
onChange={handleChange}
onDragLeave={(editor, e) => bind.onDragLeave(e)}
onDragOver={(editor, e) => bind.onDragOver(e)}
onDrop={(editor, e) => bind.onDrop(e)}
onDragEnter={(editor, e) => bind.onDragEnter(e)}
onDragLeave={(editor, e: DragEvent) => bind.onDragLeave(e)}
onDragOver={(editor, e: DragEvent) => bind.onDragOver(e)}
onDrop={(editor, e: DragEvent) => bind.onDrop(e)}
onDragEnter={(editor, e: DragEvent) => bind.onDragEnter(e)}
/>
{dragging && <SubmitDragger />}
</Box>

View File

@ -36,7 +36,7 @@ export const MarkdownField = ({
value={value}
onChange={setValue}
/>
<ErrorLabel mt="2" hasError={Boolean(error && touched)}>
<ErrorLabel mt={2} hasError={Boolean(error && touched)}>
{error}
</ErrorLabel>
</Box>

View File

@ -1,18 +1,18 @@
import React, { useState, useEffect } from 'react';
import { Box, Text, Col, Anchor, Row, Action } from '@tlon/indigo-react';
import { Action, Anchor, Box, Col, Row, Text } from '@tlon/indigo-react';
import { Association, Graph, GraphNode, Group } from '@urbit/api';
import bigInt from 'big-integer';
import React, { useEffect, useState } from 'react';
import { Link, RouteComponentProps } from 'react-router-dom';
import GlobalApi from '~/logic/api/global';
import { roleForShip } from '~/logic/lib/group';
import { Contacts, GraphNode, Graph, Association, Unreads, Group, Post } from '@urbit/api';
import { getPermalinkForGraph } from '~/logic/lib/permalinks';
import { GraphContent } from '~/views/landscape/components/Graph/GraphContent';
import { getComments, getLatestRevision } from '~/logic/lib/publish';
import { useCopy } from '~/logic/lib/useCopy';
import { useQuery } from '~/logic/lib/useQuery';
import Author from '~/views/components/Author';
import { Comments } from '~/views/components/Comments';
import { Spinner } from '~/views/components/Spinner';
import { GraphContent } from '~/views/landscape/components/Graph/GraphContent';
import { NoteNavigation } from './NoteNavigation';
import { Redirect } from 'react-router-dom';
@ -117,7 +117,7 @@ export function Note(props: NoteProps & RouteComponentProps) {
date={post?.['time-sent']}
group={group}
>
<Row px="2" gapX="2" alignItems="flex-end" height="14px">
<Row px={2} gapX={2} alignItems="flex-end" height="14px">
<Action bg="white" onClick={doCopy}>{copyDisplay}</Action>
{adminLinks}
</Row>
@ -128,8 +128,7 @@ export function Note(props: NoteProps & RouteComponentProps) {
<NoteNavigation
notebook={notebook}
noteId={noteId}
ship={props.ship}
book={props.book}
baseUrl={baseUrl}
/>
<Comments
ship={ship}

View File

@ -29,7 +29,7 @@ function NavigationItem(props: {
<Timestamp
stamp={moment(props.date)}
time={false}
fontSize="1"
fontSize={1}
justifyContent={props.prev ? 'flex-start' : 'flex-end'}
/>
</Link>
@ -48,12 +48,12 @@ function getAdjacentId(
return target?.[0] || null;
}
function makeNoteUrl(noteId: number) {
function makeNoteUrl(noteId: BigInteger) {
return noteId.toString();
}
interface NoteNavigationProps {
noteId: number;
noteId: BigInteger;
notebook: Graph;
baseUrl: string;
}

View File

@ -6,9 +6,9 @@ import ReactMarkdown from 'react-markdown';
import { Link } from 'react-router-dom';
import styled from 'styled-components';
import {
getComments,
getLatestRevision,
getSnippet
getComments,
getLatestRevision,
getSnippet
} from '~/logic/lib/publish';
import useHarkState from '~/logic/state/hark';
import Author from '~/views/components/Author';
@ -37,7 +37,7 @@ export function NotePreviewContent({ snippet }) {
style={{ backgroundSize: 'cover',
backgroundPosition: 'center' }}
>
<Image src={props.src} opacity="0" maxHeight="300px" />
<Image src={props.src} opacity={0} maxHeight="300px" />
</Box>
),
paragraph: props => (
@ -91,7 +91,7 @@ export function NotePreview(props: NotePreviewProps) {
borderRadius={2}
alignItems='flex-start'
overflow='hidden'
p='2'
p={2}
>
<WrappedBox mb={2}><Text bold>{title}</Text></WrappedBox>
<WrappedBox>
@ -101,7 +101,7 @@ export function NotePreview(props: NotePreviewProps) {
</WrappedBox>
</Col>
</Link>
<Row minWidth='0' flexShrink={0} width="100%" justifyContent="space-between" py={3} bg="white">
<Row minWidth={0} flexShrink={0} width="100%" justifyContent="space-between" py={3} bg="white">
<Author
showImage
ship={post?.author}

View File

@ -1,4 +1,5 @@
import { Association, Graph, GraphNode, Group } from '@urbit/api';
import bigInt from 'big-integer';
import React from 'react';
import { Route, RouteComponentProps, Switch } from 'react-router-dom';
import GlobalApi from '~/logic/api/global';
@ -9,7 +10,7 @@ interface NoteRoutesProps {
ship: string;
book: string;
note: GraphNode;
noteId: number;
noteId: bigInt.BigInteger;
notebook: Graph;
api: GlobalApi;
association: Association;

View File

@ -40,7 +40,7 @@ export function Notebook(props: NotebookProps & RouteComponentProps): ReactEleme
}
return (
<Col gapY="4" pt={4} mx="auto" px={3} maxWidth="768px">
<Col gapY={4} pt={4} mx="auto" px={3} maxWidth="768px">
<Row justifyContent="space-between">
<Box>
<Text display='block'>{association.metadata?.title}</Text>
@ -50,7 +50,7 @@ export function Notebook(props: NotebookProps & RouteComponentProps): ReactEleme
</Text>
</Box>
</Row>
<Box borderBottom="1" borderBottomColor="lightGray" />
<Box borderBottom={1} borderBottomColor="lightGray" />
<NotebookPosts
graph={graph}
host={ship}

View File

@ -38,7 +38,7 @@ export const Writers = (props: WritersProps): ReactElement => {
return (
<Box maxWidth='512px'>
<Text display='block'>Writers</Text>
<Text display='block' mt='2' gray>Add additional writers to this notebook</Text>
<Text display='block' mt={2} gray>Add additional writers to this notebook</Text>
<Formik
initialValues={{ ships: [] }}
onSubmit={onSubmit}
@ -49,16 +49,16 @@ export const Writers = (props: WritersProps): ReactElement => {
label=""
maxLength={undefined}
/>
<AsyncButton width='100%' mt='3' primary>
<AsyncButton width='100%' mt={3} primary>
Submit
</AsyncButton>
</Form>
</Formik>
{writers.length > 0 ? <>
<Text display='block' mt='2'>Current writers:</Text>
<Text mt='2' display='block' mono>{writers}</Text>
<Text display='block' mt={2}>Current writers:</Text>
<Text mt={2} display='block' mono>{writers}</Text>
</> :
<Text display='block' mt='2'>
<Text display='block' mt={2}>
All group members can write to this channel
</Text>
}

View File

@ -7,7 +7,7 @@ export function BackButton(props: {}) {
<Link to='/~settings'>
<Text
display={['block', 'none']}
fontSize='2'
fontSize={2}
fontWeight='medium'
p={4}
pb={0}

View File

@ -32,10 +32,10 @@ export function BackgroundPicker({
<Label>Landscape Background</Label>
<Row flexWrap="wrap" {...rowSpace}>
<Col {...colProps}>
<Radio mb="1" name="bgType" label="Image" id="url" />
<Text ml="5" gray>Set an image background</Text>
<Radio mb={1} name="bgType" label="Image" id="url" />
<Text ml={5} gray>Set an image background</Text>
<ImageInput
ml="5"
ml={5}
api={api}
id="bgUrl"
placeholder="Drop or upload a file, or paste a link here"
@ -46,13 +46,13 @@ export function BackgroundPicker({
</Row>
<Row {...rowSpace}>
<Col {...colProps}>
<Radio mb="1" label="Color" id="color" name="bgType" />
<Text ml="5" gray>Set a hex-based background</Text>
<ColorInput placeholder="FFFFFF" ml="5" id="bgColor" />
<Radio mb={1} label="Color" id="color" name="bgType" />
<Text ml={5} gray>Set a hex-based background</Text>
<ColorInput placeholder="FFFFFF" ml={5} id="bgColor" />
</Col>
</Row>
<Radio
my="3"
my={3}
caption="Your home screen will simply render as its respective day/night mode color"
name="bgType"
label="None"

View File

@ -1,13 +1,13 @@
import {
Box,
Button, ManagedForm as Form, ManagedTextInputField as Input,
Box,
Button, ManagedForm as Form, ManagedTextInputField as Input,
Menu,
MenuButton,
Menu,
MenuButton,
MenuItem, MenuList,
MenuItem, MenuList,
Row, Text
Row, Text
} from '@tlon/indigo-react';
import { Formik, FormikHelpers } from 'formik';
import React, { ReactElement, useCallback, useState } from 'react';
@ -95,12 +95,12 @@ export function BucketList({
{adding && (
<Input
placeholder="Enter your new bucket"
mt="2"
mt={2}
label="New Bucket"
id="newBucket"
/>
)}
<Row gapX="3" mt="3">
<Row gapX={3} mt={3}>
<Button type="button" onClick={() => setAdding(false)}>
Cancel
</Button>

View File

@ -1,7 +1,7 @@
import {
Col, ManagedToggleSwitchField as Toggle,
Col, ManagedToggleSwitchField as Toggle,
Text
Text
} from '@tlon/indigo-react';
import { Form, Formik, FormikHelpers } from 'formik';
import React, { useCallback } from 'react';
@ -75,8 +75,8 @@ export function CalmPrefs(props: {
<Formik initialValues={initialValues} onSubmit={onSubmit}>
<Form>
<BackButton />
<Col borderBottom="1" borderBottomColor="washedGray" p="5" pt="4" gapY="5">
<Col gapY="1" mt="0">
<Col borderBottom={1} borderBottomColor="washedGray" p={5} pt={4} gapY={5}>
<Col gapY={1} mt={0}>
<Text color="black" fontSize={2} fontWeight="medium">
CalmEngine
</Text>

View File

@ -52,7 +52,7 @@ const StoreDebugger = (props: StoreDebuggerProps) => {
backgroundColor='white'
color='black'
border='1px solid transparent'
borderRadius='2'
borderRadius={2}
fontSize={1}
placeholder="Drill Down"
width="100%"
@ -65,7 +65,7 @@ const StoreDebugger = (props: StoreDebuggerProps) => {
}
}}
/>
<Text mono p='1' borderRadius='1' display='block' overflow='auto' backgroundColor='washedGray' style={{ whiteSpace: 'pre', wordWrap: 'break-word' }}>{text}</Text>
<Text mono p={1} borderRadius={1} display='block' overflow='auto' backgroundColor='washedGray' style={{ whiteSpace: 'pre', wordWrap: 'break-word' }}>{text}</Text>
</Box>}
</Box>
);
@ -75,8 +75,8 @@ const DebugPane = () => {
return (
<>
<BackButton />
<Col borderBottom="1" borderBottomColor="washedGray" p="5" pt="4" gapY="5">
<Col gapY="1" mt="0">
<Col borderBottom={1} borderBottomColor="washedGray" p={5} pt={4} gapY={5}>
<Col gapY={1} mt={0}>
<Text color="black" fontSize={2} fontWeight="medium">
Debug Menu
</Text>

View File

@ -1,8 +1,8 @@
import {
Col,
Col,
Label,
ManagedRadioButtonField as Radio, Text
Label,
ManagedRadioButtonField as Radio, Text
} from '@tlon/indigo-react';
import { Form, Formik } from 'formik';
import React from 'react';
@ -89,8 +89,8 @@ export default function DisplayForm(props: DisplayFormProps) {
{props => (
<Form>
<BackButton />
<Col p="5" pt="4" gapY="5">
<Col gapY="1" mt="0">
<Col p={5} pt={4} gapY={5}>
<Col gapY={1} mt={0}>
<Text color="black" fontSize={2} fontWeight="medium">
Display Preferences
</Text>

View File

@ -5,12 +5,12 @@ import {
StatelessToggleSwitchField, Text
} from '@tlon/indigo-react';
import { Association, resourceFromPath } from '@urbit/api';
import { Association, GraphConfig, resourceFromPath } from '@urbit/api';
import { useField } from 'formik';
import _ from 'lodash';
import React, { useEffect, useState } from 'react';
import { isWatching } from '~/logic/lib/hark';
import { getModuleIcon } from '~/logic/lib/util';
import { getModuleIcon, GraphModule } from '~/logic/lib/util';
import useGraphState from '~/logic/state/graph';
import useHarkState from '~/logic/state/hark';
import useMetadataState, { useGraphsForGroup } from '~/logic/state/metadata';
@ -20,7 +20,7 @@ export function GroupChannelPicker(props: {}) {
const associations = useMetadataState(s => s.associations);
return (
<Col gapY="3">
<Col gapY={3}>
{_.map(associations.groups, (assoc: Association, group: string) => (
<GroupWithChannels key={group} association={assoc} />
))}
@ -62,7 +62,7 @@ function GroupWithChannels(props: { association: Association }) {
display="grid"
gridTemplateColumns="24px 24px 1fr 24px 24px"
gridTemplateRows="auto"
gridGap="2"
gridGap={2}
gridTemplateAreas="'arrow icon title graphToggle groupToggle'"
>
{Object.keys(joinedGroupGraphs).length > 0 && (
@ -112,17 +112,17 @@ function Channel(props: { association: Association }) {
setValue(!value);
};
const icon = getModuleIcon(metadata.config?.graph);
const icon = getModuleIcon((metadata.config as GraphConfig)?.graph as GraphModule);
return (
<>
<Center gridColumn="2">
<Center gridColumn={2}>
<Icon icon={icon} />
</Center>
<Box gridColumn="3">
<Box gridColumn={3}>
<Text> {metadata.title}</Text>
</Box>
<Box gridColumn="4">
<Box gridColumn={4}>
<StatelessToggleSwitchField selected={value} onChange={onChange} />
</Box>
</>

View File

@ -1,7 +1,7 @@
import {
Col,
Col,
ManagedCheckboxField, Text
ManagedCheckboxField, Text
} from '@tlon/indigo-react';
import { Form, useField, useFormikContext } from 'formik';
import _ from 'lodash';
@ -9,8 +9,8 @@ import React from 'react';
import GlobalApi from '~/logic/api/global';
import useSettingsState, { selectSettingsState } from '~/logic/state/settings';
import {
LeapCategories,
leapCategories
LeapCategories,
leapCategories
} from '~/types';
import { FormikOnBlur } from '~/views/components/FormikOnBlur';
import { ShuffleFields } from '~/views/components/ShuffleFields';
@ -73,9 +73,9 @@ export function LeapSettings(props: { api: GlobalApi; }) {
return (
<>
<BackButton />
<Col p="5" pt="4" gapY="5">
<Col gapY="1" mt="0">
<Text fontSize="2" fontWeight="medium">
<Col p={5} pt={4} gapY={5}>
<Col gapY={1} mt={0}>
<Text fontSize={2} fontWeight="medium">
Leap
</Text>
<Text gray>
@ -84,7 +84,7 @@ export function LeapSettings(props: { api: GlobalApi; }) {
</Col>
<FormikOnBlur initialValues={initialValues} onSubmit={onSubmit}>
<Form>
<Col gapY="4">
<Col gapY={4}>
<Text fontWeight="medium">
Customize default Leap sections
</Text>

View File

@ -1,7 +1,7 @@
import {
Col,
Col,
ManagedToggleSwitchField as Toggle, Text
ManagedToggleSwitchField as Toggle, Text
} from '@tlon/indigo-react';
import { Form, Formik, FormikHelpers } from 'formik';
import _ from 'lodash';
@ -72,9 +72,9 @@ export function NotificationPreferences(props: {
return (
<>
<BackButton />
<Col p="5" pt="4" gapY="5">
<Col gapY="1" mt="0">
<Text fontSize="2" fontWeight="medium">
<Col p={5} pt={4} gapY={5}>
<Col gapY={1} mt={0}>
<Text fontSize={2} fontWeight="medium">
Notification Preferences
</Text>
<Text gray>
@ -84,7 +84,7 @@ export function NotificationPreferences(props: {
</Col>
<Formik initialValues={initialValues} onSubmit={onSubmit}>
<Form>
<Col gapY="4">
<Col gapY={4}>
<Toggle
label="Do not disturb"
id="dnd"
@ -100,7 +100,7 @@ export function NotificationPreferences(props: {
id="mentions"
caption="Notify me if someone mentions my @p in a channel I've joined"
/>
<Col gapY="3">
<Col gapY={3}>
<Text lineHeight="tall">
Activity
</Text>

View File

@ -1,7 +1,7 @@
import {
Anchor, Col, ManagedForm as Form, ManagedTextInputField as Input,
Anchor, Col, ManagedForm as Form, ManagedTextInputField as Input,
Text
Text
} from '@tlon/indigo-react';
import { Formik, FormikHelpers } from 'formik';
import React, { ReactElement, useCallback } from 'react';
@ -47,7 +47,7 @@ export default function S3Form(props: S3FormProps): ReactElement {
return (
<>
<BackButton />
<Col p='5' pt='4' borderBottom='1' borderBottomColor='washedGray'>
<Col p={5} pt={4} borderBottom={1} borderBottomColor='washedGray'>
<Formik
initialValues={
{
@ -61,8 +61,8 @@ export default function S3Form(props: S3FormProps): ReactElement {
onSubmit={onSubmit}
>
<Form>
<Col maxWidth='600px' gapY='5'>
<Col gapY='1' mt='0'>
<Col maxWidth='600px' gapY={5}>
<Col gapY={1} mt={0}>
<Text color='black' fontSize={2} fontWeight='medium'>
S3 Storage Setup
</Text>
@ -72,8 +72,8 @@ export default function S3Form(props: S3FormProps): ReactElement {
<Anchor
target='_blank'
style={{ textDecoration: 'none' }}
borderBottom='1'
ml='1'
borderBottom={1}
ml={1}
href='https://urbit.org/using/os/s3/'
>
Learn more
@ -94,8 +94,8 @@ export default function S3Form(props: S3FormProps): ReactElement {
</Form>
</Formik>
</Col>
<Col maxWidth='600px' p='5' gapY='4'>
<Col gapY='1'>
<Col maxWidth='600px' p={5} gapY={4}>
<Col gapY={1}>
<Text color='black' mb={4} fontSize={2} fontWeight='medium'>
S3 Buckets
</Text>

View File

@ -1,7 +1,7 @@
import {
Button,
Col,
StatelessCheckboxField, Text
Button,
Col,
StatelessCheckboxField, Text
} from '@tlon/indigo-react';
import React, { useState } from 'react';
import GlobalApi from '~/logic/api/global';
@ -16,8 +16,8 @@ export default function SecuritySettings({ api }: SecuritySettingsProps) {
return (
<>
<BackButton />
<Col gapY="5" p="5" pt="4">
<Col gapY="1" mt="0">
<Col gapY={5} p={5} pt={4}>
<Col gapY={1} mt={0}>
<Text fontSize={2} fontWeight="medium">
Security Preferences
</Text>
@ -25,17 +25,17 @@ export default function SecuritySettings({ api }: SecuritySettingsProps) {
Manage sessions, login credentials and Landscape access
</Text>
</Col>
<Col gapY="1">
<Col gapY={1}>
<Text color="black">
Log out of this session
</Text>
<Text mb="3" gray>
<Text mb={3} gray>
{allSessions
? 'You will be logged out of all browsers that have currently logged into your Urbit.'
: 'You will be logged out of your Urbit on this browser.'}
</Text>
<StatelessCheckboxField
mb="3"
mb={3}
selected={allSessions}
onChange={() => setAllSessions(s => !s)}
>

View File

@ -10,14 +10,14 @@ export function SettingsItem(props: {
const { to, title, description } = props;
return (
<Link to={`/~settings/${to}`}>
<Row alignItems="center" gapX="3">
<Row alignItems="center" gapX={3}>
<Box
borderRadius="2"
borderRadius={2}
backgroundColor="blue"
width="64px"
height="64px"
/>
<Col gapY="2">
<Col gapY={2}>
<Text>{title}</Text>
<Text gray>{description}</Text>
</Col>
@ -28,9 +28,9 @@ export function SettingsItem(props: {
export default function Settings(props: {}) {
return (
<Col gapY="5" p="5">
<Col gapY="1">
<Text fontSize="2">System Preferences</Text>
<Col gapY={5} p={5}>
<Col gapY={1}>
<Text fontSize={2}>System Preferences</Text>
<Text gray>Configure and customize Landscape</Text>
</Col>
<Box
@ -38,7 +38,7 @@ export default function Settings(props: {}) {
width="100%"
height="100%"
gridTemplateColumns={['100%', '1fr 1fr']}
gridGap="3"
gridGap={3}
>
<SettingsItem
to="notifications"

View File

@ -60,7 +60,7 @@ function SettingsItem(props: { children: ReactNode }) {
const { children } = props;
return (
<Box borderBottom='1' borderBottomColor='lightGray'>
<Box borderBottom={1} borderBottomColor='lightGray'>
{children}
</Box>
);
@ -94,13 +94,13 @@ return;
<Skeleton>
<Col
height='100%'
borderRight='1'
borderRight={1}
borderRightColor='lightGray'
display={hash === '' ? 'flex' : ['none', 'flex']}
width='100%'
overflowY='auto'
>
<Text display='block' mt='4' mb='3' mx='3' fontSize='2' fontWeight='700'>
<Text display='block' mt={4} mb={3} mx={3} fontSize={2} fontWeight='700'>
System Preferences
</Text>
<Col>

View File

@ -1,6 +1,9 @@
import _ from 'lodash';
export default class Api {
ship: any;
channel: any;
bindPaths: any[];
constructor(ship, channel) {
this.ship = ship;
this.channel = channel;
@ -10,7 +13,7 @@ export default class Api {
bind(path, method, ship = this.ship, appl = 'herm', success, fail) {
this.bindPaths = _.uniq([...this.bindPaths, path]);
window.subscriptionId = this.channel.subscribe(ship, appl, path,
(window as any).subscriptionId = this.channel.subscribe(ship, appl, path,
(err) => {
fail(err);
},

View File

@ -12,6 +12,11 @@ import Store from './store';
import Subscription from './subscription';
class TermApp extends Component {
store: Store;
api: any;
subscription: any;
props: any;
state: any;
constructor(props) {
super(props);
this.store = new Store();
@ -27,7 +32,7 @@ class TermApp extends Component {
componentDidMount() {
this.resetControllers();
const channel = new window.channel();
const channel = new (window as any).channel();
this.api = new Api(this.props.ship, channel);
this.store.api = this.api;
@ -61,13 +66,13 @@ class TermApp extends Component {
display='flex'
>
<Col
p='3'
p={3}
backgroundColor='white'
width='100%'
minHeight='0'
minWidth='0'
minHeight={0}
minWidth={0}
color='lightGray'
borderRadius='2'
borderRadius={2}
mx={['0','3']}
mb={['0','3']}
border={['0','1']}

View File

@ -11,8 +11,8 @@ export class History extends Component {
return (
<Box
height='100%'
minHeight='0'
minWidth='0'
minHeight={0}
minWidth={0}
display='flex'
flexDirection='column-reverse'
overflowY='scroll'

View File

@ -2,6 +2,8 @@ import { BaseInput, Box, Row } from '@tlon/indigo-react';
import React, { Component } from 'react';
export class Input extends Component {
inputRef: React.RefObject<unknown>;
props: any;
constructor(props) {
super(props);
this.state = {};
@ -69,7 +71,7 @@ belt = { met: 'bac' };
}
paste(e) {
const clipboardData = e.clipboardData || window.clipboardData;
const clipboardData = e.clipboardData || (window as any).clipboardData;
const clipboardText = clipboardData.getData('Text');
this.props.api.belt({ txt: [...clipboardText] });
e.preventDefault();
@ -94,18 +96,18 @@ belt = { met: 'bac' };
}
}
return (
<Row flexGrow='1' position='relative'>
<Box flexShrink='0' width='100%' color='black' fontSize='0'>
<Row flexGrow={1} position='relative'>
<Box flexShrink={0} width='100%' color='black' fontSize={0}>
<BaseInput
autoFocus
autoCorrect="off"
autoCapitalize="off"
color='black'
minHeight='0'
minHeight={0}
display='inline-block'
width='100%'
spellCheck="false"
tabindex="0"
tabindex={0}
wrap="off"
className="mono"
id="term"

View File

@ -57,7 +57,7 @@ export default React.memo(({ line }) => {
//
return (
<Text mono display='flex'
fontSize='0'
fontSize={0}
style={{ overflowWrap: 'break-word', whiteSpace: 'pre-wrap' }}
>
{text}

View File

@ -2,6 +2,9 @@ import { saveAs } from 'file-saver';
import bel from '../../../logic/lib/bel';
export default class Store {
state: any;
api: any;
setState: any;
constructor() {
this.state = this.initialState();
}
@ -69,6 +72,7 @@ return h;
break;
case 'sag':
blit.sav = blit.sag;
break;
case 'sav':
const name = blit.sav.path.split('/').slice(-2).join('.');
const buff = new Buffer(blit.sav.file, 'base64');

View File

@ -1,4 +1,8 @@
export default class Subscription {
store: any;
api: any;
channel: any;
firstRoundComplete: boolean;
constructor(store, api, channel) {
this.store = store;
this.api = api;
@ -51,13 +55,13 @@ return;
console.error('event source error: ', err);
console.log('initiating new channel');
this.firstRoundComplete = false;
setTimeout(2000, () => {
setTimeout(() => {
this.store.handleEvent({
data: { clear : true }
});
this.start();
});
}, 2000);
}
subscribe(path, app) {

View File

@ -2,6 +2,7 @@ import { BaseImage, Box, Row } from '@tlon/indigo-react';
import moment from 'moment';
import React, { ReactElement, ReactNode, useState } from 'react';
import { useHistory } from 'react-router-dom';
import GlobalApi from '~/logic/api/global';
import { Sigil } from '~/logic/lib/sigil';
import { useCopy } from '~/logic/lib/useCopy';
import { cite, deSig, useShowNickname, uxToHex } from '~/logic/lib/util';
@ -20,7 +21,7 @@ interface AuthorProps {
unread?: boolean;
api?: GlobalApi;
size?: number;
lineHeight?: string;
lineHeight?: string | number;
isRelativeTime?: boolean;
}

View File

@ -1,18 +1,18 @@
import {
Col,
Col,
ErrorLabel, Label,
Row,
ErrorLabel, Label,
Row,
StatelessTextInput as Input
StatelessTextInput as Input
} from '@tlon/indigo-react';
import { useField } from 'formik';
import Mousetrap from 'mousetrap';
import React, {
ReactElement, ReactNode, useCallback,
ReactElement, ReactNode, useCallback,
useEffect,
useRef, useState
useEffect,
useRef, useState
} from 'react';
function Chip(props: { children: ReactNode }): ReactElement {
@ -20,9 +20,9 @@ function Chip(props: { children: ReactNode }): ReactElement {
<Row
alignItems="center"
height="24px"
borderRadius="1"
my="1"
p="1"
borderRadius={1}
my={1}
p={1}
bg="blue"
color="white"
>
@ -93,15 +93,15 @@ export function ChipInput(props: ChipInputProps): ReactElement {
}, [inputRef.current, addNewChip, newChip]);
return (
<Col gapY="2">
<Col gapY={2}>
<Label htmlFor={id}>{label}</Label>
{caption && <Label gray>{caption}</Label>}
<Row
border="1"
border={1}
borderColor="washedGray"
borderRadius="1"
pl="2"
gapX="2"
borderRadius={1}
pl={2}
gapX={2}
width="100%"
flexWrap="wrap"
minHeight="32px"
@ -114,18 +114,18 @@ export function ChipInput(props: ChipInputProps): ReactElement {
height="24px"
flexShrink={1}
flexGrow={1}
pl="0"
pl={0}
ref={inputRef}
onChange={onChange}
value={newChip}
onBlur={onBlur}
placeholder={placeholder}
border="0"
my="1"
py="1"
border={0}
my={1}
py={1}
/>
</Row>
<ErrorLabel mt="2" hasError={Boolean(meta.touched && meta.error)}>
<ErrorLabel mt={2} hasError={Boolean(meta.touched && meta.error)}>
{meta.error}
</ErrorLabel>

View File

@ -1,10 +1,10 @@
import {
Box, Col,
Box, Col,
ErrorLabel, Label,
Row,
ErrorLabel, Label,
Row,
StatelessTextInput as Input
StatelessTextInput as Input
} from '@tlon/indigo-react';
import { useField } from 'formik';
import React, { FormEvent } from 'react';
@ -40,11 +40,11 @@ export function ColorInput(props: ColorInputProps) {
<Box display='flex' flexDirection='column' {...rest}>
<Label htmlFor={id}>{label}</Label>
{caption ? (
<Label mt='2' gray>
<Label mt={2} gray>
{caption}
</Label>
) : null}
<Row mt='2' alignItems='flex-end'>
<Row mt={2} alignItems='flex-end'>
<Input
id={id}
borderTopRightRadius={0}
@ -79,7 +79,7 @@ export function ColorInput(props: ColorInputProps) {
/>
</Box>
</Row>
<ErrorLabel mt='2' hasError={Boolean(meta.touched && meta.error)}>
<ErrorLabel mt={2} hasError={Boolean(meta.touched && meta.error)}>
{meta.error}
</ErrorLabel>
</Box>

View File

@ -11,8 +11,8 @@ import { getPermalinkForGraph } from '~/logic/lib/permalinks';
import { getLatestCommentRevision } from '~/logic/lib/publish';
import { useCopy } from '~/logic/lib/useCopy';
import useMetadataState from '~/logic/state/metadata';
import { GraphContent } from '../landscape/components/Graph/GraphContent';
import Author from '~/views/components/Author';
import { GraphContent } from '../landscape/components/Graph/GraphContent';
const ClickBox = styled(Box)`
cursor: pointer;
@ -60,8 +60,9 @@ export function CommentItem(props: CommentItemProps) {
};
const ourMention = post?.contents?.some((e) => {
return e?.mention && e?.mention === window.ship;
});
if (!('mention' in e)) return false;
return e?.mention && e?.mention === window.ship;
});
if (!highlighted) {
if (ourMention) {
@ -118,7 +119,7 @@ export function CommentItem(props: CommentItemProps) {
return (
<Box ref={ref} mb={4} opacity={post?.pending ? '60%' : '100%'}>
<Row px="1" my={3}>
<Row px={1} my={3}>
<Author
showImage
ship={post?.author}
@ -127,16 +128,16 @@ export function CommentItem(props: CommentItemProps) {
group={group}
isRelativeTime
>
<Row px="2" gapX="2" height="18px">
<Row px={2} gapX={2} height="18px">
<Action bg="white" onClick={doCopy}>{copyDisplay}</Action>
{adminLinks}
</Row>
</Author>
</Row>
<GraphContent
borderRadius="1"
p="1"
mb="1"
borderRadius={1}
p={1}
mb={1}
backgroundColor={highlighted ? 'washedBlue' : 'white'}
transcluded={0}
api={api}

View File

@ -82,7 +82,7 @@ export function Comments(props: CommentsProps & PropFunc<typeof Col>) {
const post = createPost(
content,
commentNode.post.index,
parseInt(idx + 1, 10)
parseInt((idx + 1).toString(), 10).toString()
);
await api.graph.addPost(ship, name, post);
history.push(baseUrl);
@ -128,7 +128,7 @@ export function Comments(props: CommentsProps & PropFunc<typeof Col>) {
const canComment = isWriter(group, association.resource) || association.metadata.vip === 'reader-comments';
return (
<Col {...rest} minWidth='0'>
<Col {...rest} minWidth={0}>
{( !editCommentId && canComment ? <CommentInput onSubmit={onSubmit} /> : null )}
{( editCommentId ? (
<CommentInput

View File

@ -1,8 +1,8 @@
import { Box } from '@tlon/indigo-react';
import React, {
ReactElement, ReactNode,
ReactElement, ReactNode,
useCallback, useEffect, useRef, useState
useCallback, useEffect, useRef, useState
} from 'react';
import { useLocation } from 'react-router-dom';
import styled from 'styled-components';
@ -84,7 +84,7 @@ export function Dropdown(props: DropdownProps): ReactElement {
}, []);
return (
<Box flexShrink={flexShrink} position={open ? 'relative' : 'static'} minWidth='0' width={props?.width ? props.width : 'auto'}>
<Box flexShrink={flexShrink} position={open ? 'relative' : 'static'} minWidth={0} width={props?.width ? props.width : 'auto'}>
<ClickBox width='100%' ref={anchorRef} onClick={onOpen}>
{children}
</ClickBox>

View File

@ -1,14 +1,14 @@
import {
Box,
StatelessTextInput as Input
Box,
StatelessTextInput as Input
} from '@tlon/indigo-react';
import _ from 'lodash';
import Mousetrap from 'mousetrap';
import React, {
ChangeEvent,
ReactElement, useCallback,
useEffect, useMemo, useRef,
useState
ChangeEvent,
ReactElement, useCallback,
useEffect, useMemo, useRef,
useState
} from 'react';
import { useDropdown } from '~/logic/lib/useDropdown';
import { PropFunc } from '~/types/util';
@ -140,9 +140,9 @@ export function DropdownSearch<C>(props: DropdownSearchProps<C>): ReactElement {
/>
{dropdown.length !== 0 && query.length !== 0 && (
<Box
mt="1"
border="1"
borderRadius="1"
mt={1}
border={1}
borderRadius={1}
borderColor="washedGray"
bg="white"
width="100%"

View File

@ -29,7 +29,7 @@ class ErrorComponent extends Component<ErrorProps> {
body =`\`\`\`%0A${error.stack?.replaceAll('\n', '%0A')}%0A\`\`\``;
}
return (
<Col alignItems="center" justifyContent="center" height="100%" p="4" backgroundColor="white" maxHeight="100%">
<Col alignItems="center" justifyContent="center" height="100%" p={4} backgroundColor="white" maxHeight="100%">
<Box mb={4}>
<Text fontSize={3}>
{code ? code : 'Error'}

View File

@ -2,9 +2,9 @@ import { Box, Button, Row } from '@tlon/indigo-react';
import { useFormikContext } from 'formik';
import _ from 'lodash';
import React, {
useCallback, useEffect,
useCallback, useEffect,
useMemo, useState
useMemo, useState
} from 'react';
import { Prompt } from 'react-router-dom';
import { FormGroupContext, SubmitHandler } from '~/logic/lib/formGroup';
@ -152,10 +152,10 @@ export function FormGroup(props: { onReset?: () => void; } & PropFunc<typeof Box
width="100%"
position="sticky"
bottom="0px"
p="3"
gapX="2"
p={3}
gapX={2}
backgroundColor="white"
borderTop="1"
borderTop={1}
borderTopColor="washedGray"
>
<Button onClick={resetAll}>Cancel</Button>

View File

@ -22,10 +22,10 @@ export function FormSubmit<T = unknown>(props: FormSubmitProps): ReactElement {
return (
<Row
p="2"
p={2}
bottom="0px"
justifyContent={props.start ? 'flex-start' : 'flex-end'}
gapX="2"
gapX={2}
alignItems="center"
>
{dirty && !isSubmitting && (

View File

@ -1,7 +1,7 @@
import { Box, Col, Icon, Row, Text } from '@tlon/indigo-react';
import { MetadataUpdatePreview } from '@urbit/api';
import React, { ReactElement, useEffect, useLayoutEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { Box, Text, Row, Col, Icon } from '@tlon/indigo-react';
import { Associations, Groups } from '@urbit/api';
import GlobalApi from '~/logic/api/global';
import { useModal } from '~/logic/lib/useModal';
import { useVirtual } from '~/logic/lib/virtualContext';
@ -62,16 +62,16 @@ export function GroupLink(
width="fit-content"
flexShrink={1}
alignItems="center"
py="2"
pr="2"
py={2}
pr={2}
onClick={
joined ? () => history.push(`/~landscape/ship/${name}`) : showModal
}
opacity={preview ? '1' : '0.6'}
>
<MetadataIcon height={6} width={6} metadata={preview ? preview.metadata : { 'color': '0x0' }} />
<MetadataIcon height={6} width={6} metadata={preview ? preview.metadata : { color: '0x0' , picture: ''}} />
<Col>
<Text ml="2" fontWeight="medium" mono={!preview}>
<Text ml={2} fontWeight="medium" mono={!preview}>
{preview ? preview.metadata.title : name}
</Text>
<Box pt='1' ml='2' display='flex' alignItems='center'>

View File

@ -1,10 +1,10 @@
import {
Box,
Box,
Col,
Col,
ErrorLabel, Icon, Label,
Row, Text
ErrorLabel, Icon, Label,
Row, Text
} from '@tlon/indigo-react';
import { Association } from '@urbit/api/metadata';
import { FieldArray, useFormikContext } from 'formik';
@ -132,12 +132,12 @@ export function GroupSearch<I extends string, V extends FormValues<I>>(props: Gr
<Col>
<Label htmlFor={id}>{label}</Label>
{caption && (
<Label gray mt="2">
<Label gray mt={2}>
{caption}
</Label>
)}
<DropdownSearch<Association>
mt="2"
mt={2}
candidates={groups}
placeholder="Search for groups..."
disabled={props.maxLength ? value.length >= props.maxLength : false}
@ -156,16 +156,16 @@ export function GroupSearch<I extends string, V extends FormValues<I>>(props: Gr
return (
<Row
key={e}
borderRadius="1"
mt="2"
borderRadius={1}
mt={2}
width="fit-content"
border="1"
border={1}
borderColor="gray"
height="32px"
px="2"
px={2}
alignItems="center"
>
<Text mr="2">{title || e}</Text>
<Text mr={2}>{title || e}</Text>
<Icon onClick={() => onRemove(idx)} icon="X" />
</Row>
);

View File

@ -1,9 +1,9 @@
import {
BaseLabel, Box,
BaseLabel, Box,
Col, Icon,
Col, Icon,
Label, Row
Label, Row
} from '@tlon/indigo-react';
import { useField } from 'formik';
import React, { useCallback, useMemo } from 'react';
@ -86,7 +86,7 @@ return indicator.state.offError;
}, [selected, disabled, hasError]);
return (
<Box borderRadius="1" border="1" {...rest} {...style}>
<Box borderRadius={1} border={1} {...rest} {...style}>
{children}
</Box>
);
@ -121,10 +121,10 @@ export function IconRadio(props: IconRadioProps) {
hasError={meta.touched && meta.error !== undefined}
selected={field.checked}
disabled={disabled}
mr="2"
mr={2}
>
<Icon
m="2"
m={2}
color={field.checked ? 'white' : 'black'}
icon={icon as any}
/>
@ -132,7 +132,7 @@ export function IconRadio(props: IconRadioProps) {
<Col justifyContent="space-around">
<Label color={field.checked ? 'blue' : 'black'}>{label}</Label>
{caption ? (
<Label gray mt="2">
<Label gray mt={2}>
{caption}
</Label>
) : null}

View File

@ -139,11 +139,11 @@ export function ImageInput(props: ImageInputProps): ReactElement {
<Box display="flex" flexDirection="column" {...props}>
<Label htmlFor={id}>{label}</Label>
{caption ? (
<Label mt="2" gray>
<Label mt={2} gray>
{caption}
</Label>
) : null}
<Row mt="2" alignItems="flex-end" position='relative' width='100%'>
<Row mt={2} alignItems="flex-end" position='relative' width='100%'>
{prompt(field, uploading, meta, clickUploadButton)}
{clearButton(field, uploading, clearEvt)}
{uploadingStatus(uploading, meta)}

View File

@ -2,18 +2,15 @@ import { css } from '@styled-system/css';
import {
Box,
Icon,
LoadingSpinner, Row, Text
} from '@tlon/indigo-react';
import {
Invite, joinProgress,
JoinRequest,
Metadata, MetadataUpdatePreview,
resourceFromPath
} from '@urbit/api';
import { GraphConfig } from '@urbit/api/dist';
import _ from 'lodash';
import React, { ReactElement, ReactNode, useCallback } from 'react';
import { useHistory } from 'react-router-dom';
@ -81,10 +78,10 @@ function inviteUrl(hidden: boolean, resource: string, metadata?: Metadata) {
return `/~landscape${resource}`;
}
if (metadata?.config.graph === 'chat') {
return `/~landscape/messages/resource/${metadata?.config?.graph}${resource}`;
if ((metadata?.config as GraphConfig).graph === 'chat') {
return `/~landscape/messages/resource/${(metadata?.config as GraphConfig)?.graph}${resource}`;
} else {
return `/~landscape/home/resource/${metadata?.config?.graph}${resource}`;
return `/~landscape/home/resource/${(metadata?.config as GraphConfig)?.graph}${resource}`;
}
}
function InviteMetadata(props: {
@ -99,7 +96,7 @@ function InviteMetadata(props: {
}
const container = (children: ReactNode) => (
<Row overflow="hidden" height="4" gapX="2" alignItems="center">
<Row overflow="hidden" height={4} gapX={2} alignItems="center">
{children}
</Row>
);
@ -137,7 +134,7 @@ function InviteStatus(props: { status?: JoinRequest }) {
const current = status && joinProgress.indexOf(status.progress);
const desc = _.isNumber(current) && description[current];
return (
<Row gapX="1" alignItems="center" height={4}>
<Row gapX={1} alignItems="center" height={4}>
{ status.progress === 'done' ? <Icon icon="Checkmark" /> : <LoadingSpinner dark /> }
<Text gray>{desc}</Text>
</Row>
@ -230,7 +227,7 @@ function InviteActions(props: {
if (status) {
return (
<Row gapX="2" alignItems="center" height={4}>
<Row gapX={2} alignItems="center" height={4}>
<StatelessAsyncButton
height={4}
backgroundColor="white"
@ -243,7 +240,7 @@ function InviteActions(props: {
}
return (
<Row gapX="2" alignItems="center" height={4}>
<Row gapX={2} alignItems="center" height={4}>
<StatelessAsyncButton
color="blue"
height={4}
@ -302,7 +299,7 @@ export function GroupInvite(props: GroupInviteProps): ReactElement {
<NotificationWrapper api={api}>
<Header content {...headerProps} />
<Row onClick={onClick} height={[null, 4]} alignItems="flex-start" gridArea="main">
<Elbow mx="2" />
<Elbow mx={2} />
<ResponsiveRow
gapXY={[1, 2]}
height={[null, 4]}

View File

@ -24,15 +24,15 @@ export function InviteSkeleton(
} = props;
return (
<>
<Col width="100%" p="1" {...rest}>
<Col width="100%" p={1} {...rest}>
{children}
<Row px="4" gapX="4">
<Row px={4} gapX={4}>
<StatelessAsyncAction
name="accept"
bg="transparent"
onClick={onAccept}
color="blue"
mr="2"
mr={2}
>
{acceptDesc}
</StatelessAsyncAction>

View File

@ -16,7 +16,7 @@ export function JoinSkeleton(props: JoinSkeletonProps): ReactElement {
const { api, resource, children, status, ...rest } = props;
return (
<>
<Col p="1" {...rest}>
<Col p={1} {...rest}>
{children}
<JoiningStatus api={api} resource={resource} status={status} />
</Col>

View File

@ -40,7 +40,7 @@ export function MentionText(props: MentionTextProps) {
export function Mention(props: {
ship: string;
first?: boolean;
api: any;
api: GlobalApi;
}) {
const { ship, first, api, ...rest } = props;
const contact = useContact(`~${deSig(ship)}`);

View File

@ -1,17 +1,20 @@
import { Box, ColProps } from '@tlon/indigo-react';
import { Contact, Group } from '@urbit/api';
import { History } from 'history';
import React, { useEffect, useRef, useState } from 'react';
import GlobalApi from '~/logic/api/global';
import ProfileOverlay, { OVERLAY_HEIGHT } from './ProfileOverlay';
type OverlaySigilProps = ColProps & {
api: any;
api: GlobalApi;
className: string;
color: string;
contact?: Contact;
group?: Group;
history: any;
history: History;
scrollWindow?: HTMLElement;
ship: string;
onDismiss: () => void;
};
interface OverlaySigilState {
@ -36,8 +39,8 @@ export const OverlaySigil = (props: OverlaySigilProps) => {
...rest
} = { ...props };
const containerRef = useRef(null);
const [visible, setVisible] = useState<OverlaySigilState.visible>();
const [space, setSpace] = useState<OverlaySigilState.space>({
const [visible, setVisible] = useState<OverlaySigilState['visible']>();
const [space, setSpace] = useState<OverlaySigilState['space']>({
top: 'auto',
bottom: 'auto'
});
@ -86,14 +89,10 @@ export const OverlaySigil = (props: OverlaySigilProps) => {
>
<ProfileOverlay
api={api}
bottomSpace={space.bottom}
bottom={space.bottom}
color={color}
contact={contact}
group={group}
history={history}
onDismiss={onDismiss}
ship={ship}
topSpace={space.top}
top={space.top}
{...rest}
/>
</Box>

View File

@ -1,29 +1,34 @@
import React, { useCallback, useEffect, useRef, useState, useMemo, ReactNode } from 'react';
import { uxToHex, cite } from '@urbit/api';
import { useShowNickname } from '~/logic/lib/util';
import {
BaseImage, Box,
BoxProps,
Center, Col,
Icon, Row,
Text
} from '@tlon/indigo-react';
import { cite, uxToHex } from '@urbit/api';
import _ from 'lodash';
import React, { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useHistory } from 'react-router-dom';
import VisibilitySensor from 'react-visibility-sensor';
import styled from 'styled-components';
import { getRelativePosition } from '~/logic/lib/relativePosition';
import { Sigil } from '~/logic/lib/sigil';
import {
Box,
Row,
Col,
Text,
BaseImage,
Icon,
BoxProps,
Center
} from '@tlon/indigo-react';
import RichText from './RichText';
import { ProfileStatus } from './ProfileStatus';
import useSettingsState from '~/logic/state/settings';
import { useOutsideClick } from '~/logic/lib/useOutsideClick';
import { useCopy } from '~/logic/lib/useCopy';
import { useOutsideClick } from '~/logic/lib/useOutsideClick';
import { useShowNickname } from '~/logic/lib/util';
import { useContact } from '~/logic/state/contact';
import useSettingsState from '~/logic/state/settings';
import { Portal } from './Portal';
import { ProfileStatus } from './ProfileStatus';
import RichText from './RichText';
export const OVERLAY_HEIGHT = 250;
const FixedOverlay = styled(Col)`
@ -37,7 +42,7 @@ const FixedOverlay = styled(Col)`
type ProfileOverlayProps = BoxProps & {
ship: string;
api: any;
children: ReactNode;
children?: ReactNode;
color?: string;
};
@ -143,7 +148,7 @@ const ProfileOverlay = (props: ProfileOverlayProps) => {
borderColor='lightGray'
boxShadow='0px 0px 0px 3px'
zIndex={3}
fontSize='0'
fontSize={0}
height='250px'
width='250px'
padding={3}
@ -172,7 +177,7 @@ const ProfileOverlay = (props: ProfileOverlayProps) => {
<Col
position='absolute'
overflow='hidden'
minWidth='0'
minWidth={0}
width='100%'
padding={3}
bottom={0}
@ -185,7 +190,7 @@ const ProfileOverlay = (props: ProfileOverlayProps) => {
textOverflow='ellipsis'
overflow='hidden'
whiteSpace='pre'
marginBottom='0'
marginBottom={0}
cursor='pointer'
display={didCopy ? 'none' : 'block'}
onClick={doCopy}
@ -194,7 +199,7 @@ const ProfileOverlay = (props: ProfileOverlayProps) => {
</Text>
<Text
fontWeight='600'
marginBottom='0'
marginBottom={0}
>
{copyDisplay}
</Text>
@ -209,11 +214,11 @@ const ProfileOverlay = (props: ProfileOverlayProps) => {
<RichText
display='inline-block'
width='100%'
minWidth='0'
minWidth={0}
textOverflow='ellipsis'
overflow='hidden'
whiteSpace='pre'
marginBottom='0'
marginBottom={0}
disableRemoteContent
gray
title={contact?.status ? contact.status : ''}

View File

@ -7,14 +7,14 @@ const ReconnectButton = ({ connection, subscription }) => {
if (connectedStatus === 'disconnected') {
return (
<Button onClick={reconnect} borderColor='red' px='2'>
<Button onClick={reconnect} borderColor='red' px={2}>
<Text display={['none', 'inline']} textAlign='middle' color='red'>Reconnect</Text>
<Text color='red'> </Text>
</Button>
);
} else if (connectedStatus === 'reconnecting') {
return (
<Button borderColor='yellow' px='2' onClick={() => {}} cursor='default'>
<Button borderColor='yellow' px={2} onClick={() => {}} cursor='default'>
<LoadingSpinner pr={['0','2']} foreground='scales.yellow60' background='scales.yellow30' />
<Text display={['none', 'inline']} textAlign='middle' color='yellow'>Reconnecting</Text>
</Button>

View File

@ -21,6 +21,7 @@ type RemoteContentProps = VirtualContextProps & {
textProps?: any;
style?: any;
transcluded?: any;
className?: string;
}
interface RemoteContentState {
@ -132,15 +133,15 @@ return;
wrapInLink(contents, textOnly = false, unfold = false, unfoldEmbed = null, embedContainer = null, flushPadding = false, noOp = false) {
const { style } = this.props;
return (
<Box borderRadius="1" backgroundColor="washedGray" maxWidth="min(100%, 20rem)">
<Box borderRadius={1} backgroundColor="washedGray" maxWidth="min(100%, 20rem)">
<Row
alignItems="center"
gapX="1"
gapX={1}
>
{ textOnly && (<Icon ml="2" display="block" icon="ArrowExternal" />)}
{ textOnly && (<Icon ml={2} display="block" icon="ArrowExternal" />)}
{ !textOnly && unfoldEmbed && (
<Icon
ml='2'
ml={2}
display='block'
onClick={unfoldEmbed}
icon={unfold ? 'TriangleSouth' : 'TriangleEast'}
@ -156,7 +157,7 @@ return;
whiteSpace="nowrap"
overflow="hidden"
textOverflow="ellipsis"
minWidth="0"
minWidth={0}
width={textOnly ? 'calc(100% - 24px)' : 'fit-content'}
maxWidth="min(500px, 100%)"
style={{ color: 'inherit', textDecoration: 'none', ...style }}
@ -318,7 +319,7 @@ return;
}
const renderEmbed = !(this.state.embed !== 'error' && this.state.embed?.html);
const embed = <Box
mb='2'
mb={2}
width='100%'
flexShrink={0}
display={this.state.unfold ? 'block' : 'none'}

View File

@ -1,8 +1,10 @@
import { Anchor, Text } from '@tlon/indigo-react';
import { Contact, Group } from '@urbit/api';
import React from 'react';
import ReactMarkdown from 'react-markdown';
import ReactMarkdown, { ReactMarkdownProps } from 'react-markdown';
import RemarkDisableTokenizers from 'remark-disable-tokenizers';
import { isValidPatp } from 'urbit-ob';
import GlobalApi from '~/logic/api/global';
import { deSig } from '~/logic/lib/util';
import { PermalinkEmbed } from '~/views/apps/permalinks/embed';
import { Mention } from '~/views/components/MentionText';
@ -21,7 +23,20 @@ const DISABLED_BLOCK_TOKENS = [
const DISABLED_INLINE_TOKENS = [];
const RichText = React.memo(({ disableRemoteContent, api, ...props }) => (
type RichTextProps = ReactMarkdownProps & {
api: GlobalApi;
disableRemoteContent?: boolean;
contact?: Contact;
group?: Group;
pending?: boolean;
transcluded?: number;
inline?: boolean;
color?: string;
children?: any;
width?: string;
}
const RichText = React.memo(({ disableRemoteContent = false, api, ...props }: RichTextProps) => (
<ReactMarkdown
{...props}
renderers={{
@ -80,7 +95,7 @@ const RichText = React.memo(({ disableRemoteContent, api, ...props }) => (
);
},
paragraph: (paraProps) => {
return <Text display={props.inline ? 'inline' : 'block'} mb='2' {...props}>{paraProps.children}</Text>;
return <Text display={props.inline ? 'inline' : 'block'} mb={2} {...props}>{paraProps.children}</Text>;
}
}}
plugins={[[

View File

@ -1,18 +1,18 @@
import {
Col,
ErrorLabel, Icon, Label,
Col,
ErrorLabel, Icon, Label,
Row, Text
Row, Text
} from '@tlon/indigo-react';
import { Groups, Rolodex } from '@urbit/api';
import { FieldArray, useFormikContext } from 'formik';
import _ from 'lodash';
import React, {
ChangeEvent,
ChangeEvent,
ReactElement, useCallback, useMemo,
ReactElement, useCallback, useMemo,
useRef
useRef
} from 'react';
import ob from 'urbit-ob';
import * as Yup from 'yup';
@ -181,13 +181,13 @@ export function ShipSearch<I extends string, V extends Value<I>>(
<Col>
<Label htmlFor={id}>{label}</Label>
{caption && (
<Label gray mt="2">
<Label gray mt={2}>
{caption}
</Label>
)}
<DropdownSearch<string>
mt="2"
mt={2}
isExact={isExact}
placeholder="Search for ships"
candidates={peers}
@ -210,7 +210,7 @@ export function ShipSearch<I extends string, V extends Value<I>>(
py={1}
px={2}
color="black"
borderRadius="2"
borderRadius={2}
bg="washedGray"
fontSize={0}
mt={2}
@ -226,7 +226,7 @@ export function ShipSearch<I extends string, V extends Value<I>>(
</Row>
))}
</Row>
<ErrorLabel mt="3" hasError={error.length > 0}>
<ErrorLabel mt={3} hasError={error.length > 0}>
{error.join(', ')}
</ErrorLabel>
</Col>

View File

@ -1,9 +1,9 @@
import { Box, Icon } from '@tlon/indigo-react';
import {
FieldArray,
FieldArrayRenderProps,
FieldArray,
FieldArrayRenderProps,
useFormikContext
useFormikContext
} from 'formik';
import React, { ReactNode, useMemo } from 'react';
@ -38,11 +38,11 @@ export function ShuffleFields<N extends string, T, F extends Value<N, T>>(
}
};
return (
<Box gridColumnGap="2" gridRowGap="3" display="grid" gridAutoRows="auto" gridTemplateColumns="32px 32px 1fr">
<Box gridColumnGap={2} gridRowGap={3} display="grid" gridAutoRows="auto" gridTemplateColumns="32px 32px 1fr">
{fields.map((field, i) => (
<React.Fragment key={i}>
<Icon width="3" height="3" icon="ChevronNorth" onClick={goUp(i)} />
<Icon width="3" height="3" icon="ChevronSouth" onClick={goDown(i)} />
<Icon width={3} height={3} icon="ChevronNorth" onClick={goUp(i)} />
<Icon width={3} height={3} icon="ChevronSouth" onClick={goDown(i)} />
{children(i, arrayHelpers)}
</React.Fragment>
))}

View File

@ -6,13 +6,13 @@ const Spinner = ({
text = '',
awaiting = false
}) => awaiting ? (
<Text zIndex='2' display='flex' className={classes}>
<Text zIndex={2} display='flex' className={classes}>
<LoadingSpinner
foreground='black'
background='gray'
style={{ flexShrink: 0 }}
/>
<Text display='inline-block' ml='2' verticalAlign='middle' flexShrink='0'>{text}</Text>
<Text display='inline-block' ml={2} verticalAlign='middle' flexShrink={0}>{text}</Text>
</Text>
) : null;

View File

@ -26,7 +26,7 @@ export function StatelessAsyncToggle({
) : state === 'loading' ? (
<LoadingSpinner foreground={'white'} background="gray" />
) : state === 'success' ? (
<Text mx="2">Done</Text>
<Text mx={2}>Done</Text>
) : (
<Toggle onClick={handleClick} {...rest} />
);

View File

@ -67,16 +67,16 @@ const StatusBar = (props) => {
width='100%'
gridTemplateRows='30px'
gridTemplateColumns='3fr 1fr'
py='3'
px='3'
pb='3'
py={3}
px={3}
pb={3}
>
<Row collapse>
<Button
width='32px'
borderColor='lightGray'
mr='2'
px='2'
mr={2}
px={2}
onClick={() => history.push('/')}
{...props}
>
@ -103,13 +103,13 @@ const StatusBar = (props) => {
</Row>
<Row justifyContent='flex-end' collapse>
<StatusBarItem
mr='2'
mr={2}
backgroundColor='yellow'
display={
process.env.LANDSCAPE_STREAM === 'development' ? 'flex' : 'none'
}
justifyContent='flex-end'
flexShrink='0'
flexShrink={0}
onClick={() =>
window.open(
'https://github.com/urbit/landscape/issues/new' +
@ -132,7 +132,7 @@ const StatusBar = (props) => {
width='auto'
alignY='top'
alignX='right'
flexShrink={'0'}
flexShrink={0}
offsetY={-48}
options={
<Col
@ -167,7 +167,7 @@ const StatusBar = (props) => {
System Preferences
</Row>
<Row px={3} pt={2} pb={1} flexDirection='column'>
<Text color='gray' fontWeight='500' mb='1'>
<Text color='gray' fontWeight='500' mb={1}>
Set Status:
</Text>
<ProfileStatus
@ -182,7 +182,7 @@ const StatusBar = (props) => {
<StatusBarItem
px={xPadding}
width='32px'
flexShrink='0'
flexShrink={0}
backgroundColor={bgColor}
>
{profileImage}

View File

@ -3,10 +3,10 @@ import React, { ReactElement } from 'react';
const SubmitDragger = (): ReactElement => (
<Box
top='0'
bottom='0'
left='0'
right='0'
top={0}
bottom={0}
left={0}
right={0}
position='absolute'
backgroundColor='white'
height='100%'
@ -16,7 +16,7 @@ const SubmitDragger = (): ReactElement => (
justifyContent='center'
style={{ pointerEvents: 'none', zIndex: 999 }}
>
<Text fontSize='1' color='black'>
<Text fontSize={1} color='black'>
Drop a file to upload
</Text>
</Box>

Some files were not shown because too many files have changed in this diff Show More