mirror of
https://github.com/urbit/shrub.git
synced 2024-12-21 18:01:32 +03:00
Merge pull request #4872 from urbit/tbcs/typescript-cleanup
more typescript cleanup
This commit is contained in:
commit
181f6652ba
@ -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>
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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}
|
||||
>
|
||||
|
@ -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)) {
|
@ -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 = {};
|
||||
|
@ -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]
|
||||
));
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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>
|
||||
|
@ -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]
|
||||
);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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%">
|
||||
|
@ -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 “tutorial” 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>
|
||||
|
@ -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>)
|
||||
|
@ -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}
|
||||
/>
|
||||
);
|
||||
|
@ -21,7 +21,7 @@ const BasicTile = (props: BasicTileProps): ReactElement => (
|
||||
display='inline-block'
|
||||
verticalAlign='top'
|
||||
mt='5px'
|
||||
mr='2'
|
||||
mr={2}
|
||||
/>
|
||||
: null
|
||||
}{props.title}
|
||||
|
@ -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,
|
||||
|
@ -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'
|
||||
|
@ -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 = (
|
||||
|
@ -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>
|
||||
|
@ -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}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
)}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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} />
|
||||
|
@ -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}
|
||||
|
@ -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 = {
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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}`
|
||||
)}
|
||||
/>;
|
||||
}
|
||||
|
@ -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}
|
||||
/>
|
||||
|
@ -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}`;
|
||||
|
@ -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={() => {
|
||||
|
@ -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)}`)}
|
||||
|
@ -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 => (
|
||||
|
@ -36,7 +36,7 @@ export default function ProfileScreen(props: any) {
|
||||
border={1}
|
||||
borderColor='lightGray'
|
||||
overflowY='auto'
|
||||
flexGrow
|
||||
flexGrow={1}
|
||||
>
|
||||
<Box>
|
||||
<Profile
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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}
|
||||
|
@ -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;
|
||||
|
@ -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}
|
||||
|
@ -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>
|
||||
}
|
||||
|
@ -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}
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
</>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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)}
|
||||
>
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
},
|
||||
|
@ -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']}
|
||||
|
@ -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'
|
||||
|
@ -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"
|
||||
|
@ -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}
|
||||
|
@ -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');
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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%"
|
||||
|
@ -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'}
|
||||
|
@ -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>
|
||||
|
@ -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 && (
|
||||
|
@ -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'>
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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}
|
||||
|
@ -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)}
|
||||
|
@ -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]}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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)}`);
|
||||
|
@ -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>
|
||||
|
@ -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 : ''}
|
||||
|
@ -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>
|
||||
|
@ -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'}
|
||||
|
@ -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={[[
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
))}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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} />
|
||||
);
|
||||
|
@ -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}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user