mirror of
https://github.com/urbit/shrub.git
synced 2024-12-24 11:24:21 +03:00
commit
3922cfb2ef
@ -23,9 +23,10 @@ export const Sigil = memo(
|
||||
size,
|
||||
svgClass = '',
|
||||
icon = false,
|
||||
padding = 0
|
||||
padding = 0,
|
||||
display = 'inline-block'
|
||||
}) => {
|
||||
const innerSize = Number(size) - 2*padding;
|
||||
const innerSize = Number(size) - 2 * padding;
|
||||
const paddingPx = `${padding}px`;
|
||||
const foregroundColor = foreground
|
||||
? foreground
|
||||
@ -34,14 +35,14 @@ export const Sigil = memo(
|
||||
<Box
|
||||
backgroundColor={color}
|
||||
borderRadius={icon ? '1' : '0'}
|
||||
display='inline-block'
|
||||
display={display}
|
||||
height={size}
|
||||
width={size}
|
||||
className={classes}
|
||||
/>
|
||||
) : (
|
||||
<Box
|
||||
display='inline-block'
|
||||
display={display}
|
||||
borderRadius={icon ? '1' : '0'}
|
||||
flexBasis={size}
|
||||
backgroundColor={color}
|
||||
|
@ -24,7 +24,7 @@ type ChatInputProps = IuseStorage & {
|
||||
message: string;
|
||||
deleteMessage(): void;
|
||||
hideAvatars: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
interface ChatInputState {
|
||||
inCodeMode: boolean;
|
||||
@ -60,20 +60,23 @@ class ChatInput extends Component<ChatInputProps, ChatInputState> {
|
||||
|
||||
submit(text) {
|
||||
const { props, state } = this;
|
||||
const [,,ship,name] = props.station.split('/');
|
||||
const [, , ship, name] = props.station.split('/');
|
||||
if (state.inCodeMode) {
|
||||
this.setState({
|
||||
this.setState(
|
||||
{
|
||||
inCodeMode: false
|
||||
}, async () => {
|
||||
},
|
||||
async () => {
|
||||
const output = await props.api.graph.eval(text);
|
||||
const contents: Content[] = [{ code: { output, expression: text } }];
|
||||
const post = createPost(contents);
|
||||
props.api.graph.addPost(ship, name, post);
|
||||
});
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const post = createPost(tokenizeMessage((text)));
|
||||
const post = createPost(tokenizeMessage(text));
|
||||
|
||||
props.deleteMessage();
|
||||
|
||||
@ -86,8 +89,8 @@ class ChatInput extends Component<ChatInputProps, ChatInputState> {
|
||||
this.chatEditor.current.editor.setValue(url);
|
||||
this.setState({ uploadingPaste: false });
|
||||
} else {
|
||||
const [,,ship,name] = props.station.split('/');
|
||||
props.api.graph.addPost(ship,name, createPost([{ url }]));
|
||||
const [, , ship, name] = props.station.split('/');
|
||||
props.api.graph.addPost(ship, name, createPost([{ url }]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,7 +113,8 @@ class ChatInput extends Component<ChatInputProps, ChatInputState> {
|
||||
return;
|
||||
}
|
||||
Array.from(files).forEach((file) => {
|
||||
this.props.uploadDefault(file)
|
||||
this.props
|
||||
.uploadDefault(file)
|
||||
.then(this.uploadSuccess)
|
||||
.catch(this.uploadError);
|
||||
});
|
||||
@ -119,32 +123,40 @@ class ChatInput extends Component<ChatInputProps, ChatInputState> {
|
||||
render() {
|
||||
const { props, state } = this;
|
||||
|
||||
const color = props.ourContact
|
||||
? uxToHex(props.ourContact.color) : '000000';
|
||||
const color = props.ourContact ? uxToHex(props.ourContact.color) : '000000';
|
||||
|
||||
const sigilClass = props.ourContact
|
||||
? '' : 'mix-blend-diff';
|
||||
const sigilClass = props.ourContact ? '' : 'mix-blend-diff';
|
||||
|
||||
const avatar = (
|
||||
props.ourContact &&
|
||||
((props.ourContact?.avatar) && !props.hideAvatars)
|
||||
)
|
||||
? <BaseImage
|
||||
const avatar =
|
||||
props.ourContact && props.ourContact?.avatar && !props.hideAvatars ? (
|
||||
<BaseImage
|
||||
src={props.ourContact.avatar}
|
||||
height={16}
|
||||
width={16}
|
||||
height={24}
|
||||
width={24}
|
||||
style={{ objectFit: 'cover' }}
|
||||
borderRadius={1}
|
||||
display='inline-block'
|
||||
/>
|
||||
: <Sigil
|
||||
) : (
|
||||
<Box
|
||||
width={24}
|
||||
height={24}
|
||||
display='flex'
|
||||
justifyContent='center'
|
||||
alignItems='center'
|
||||
backgroundColor={`#${color}`}
|
||||
borderRadius={1}
|
||||
>
|
||||
<Sigil
|
||||
ship={window.ship}
|
||||
size={16}
|
||||
color={`#${color}`}
|
||||
classes={sigilClass}
|
||||
icon
|
||||
padding={2}
|
||||
/>;
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
||||
return (
|
||||
<Row
|
||||
@ -158,7 +170,7 @@ class ChatInput extends Component<ChatInputProps, ChatInputState> {
|
||||
className='cf'
|
||||
zIndex={0}
|
||||
>
|
||||
<Row p='2' alignItems='center'>
|
||||
<Row p='12px 8px 12px 12px' alignItems='center'>
|
||||
{avatar}
|
||||
</Row>
|
||||
<ChatEditor
|
||||
@ -170,31 +182,23 @@ class ChatInput extends Component<ChatInputProps, ChatInputState> {
|
||||
onPaste={this.onPaste.bind(this)}
|
||||
placeholder='Message...'
|
||||
/>
|
||||
<Box
|
||||
mx={2}
|
||||
flexShrink={0}
|
||||
height='16px'
|
||||
width='16px'
|
||||
flexBasis='16px'
|
||||
>
|
||||
{this.props.canUpload
|
||||
? this.props.uploading
|
||||
? <LoadingSpinner />
|
||||
: <Icon icon='Links'
|
||||
width="16"
|
||||
height="16"
|
||||
onClick={() => this.props.promptUpload().then(this.uploadSuccess)}
|
||||
/>
|
||||
: null
|
||||
<Box mx={2} flexShrink={0} height='16px' width='16px' flexBasis='16px'>
|
||||
{this.props.canUpload ? (
|
||||
this.props.uploading ? (
|
||||
<LoadingSpinner />
|
||||
) : (
|
||||
<Icon
|
||||
icon='Links'
|
||||
width='16'
|
||||
height='16'
|
||||
onClick={() =>
|
||||
this.props.promptUpload().then(this.uploadSuccess)
|
||||
}
|
||||
/>
|
||||
)
|
||||
) : null}
|
||||
</Box>
|
||||
<Box
|
||||
mr={2}
|
||||
flexShrink={0}
|
||||
height='16px'
|
||||
width='16px'
|
||||
flexBasis='16px'
|
||||
>
|
||||
<Box mr={2} flexShrink={0} height='16px' width='16px' flexBasis='16px'>
|
||||
<Icon
|
||||
icon='Dojo'
|
||||
onClick={this.toggleCode}
|
||||
@ -206,4 +210,6 @@ class ChatInput extends Component<ChatInputProps, ChatInputState> {
|
||||
}
|
||||
}
|
||||
|
||||
export default withLocalState(withStorage(ChatInput, { accept: 'image/*' }), ['hideAvatars']);
|
||||
export default withLocalState(withStorage(ChatInput, { accept: 'image/*' }), [
|
||||
'hideAvatars'
|
||||
]);
|
||||
|
@ -35,10 +35,10 @@ import RemoteContent from '~/views/components/RemoteContent';
|
||||
import { Mention } from '~/views/components/MentionText';
|
||||
import styled from 'styled-components';
|
||||
import useLocalState from '~/logic/state/local';
|
||||
import useSettingsState, {selectCalmState} from "~/logic/state/settings";
|
||||
import useSettingsState, { selectCalmState } from '~/logic/state/settings';
|
||||
import Timestamp from '~/views/components/Timestamp';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import {useIdlingState} from '~/logic/lib/idling';
|
||||
import { useIdlingState } from '~/logic/lib/idling';
|
||||
|
||||
export const DATESTAMP_FORMAT = '[~]YYYY.M.D';
|
||||
|
||||
@ -64,7 +64,8 @@ export const DayBreak = ({ when, shimTop = false }: DayBreakProps) => (
|
||||
</Row>
|
||||
);
|
||||
|
||||
export const UnreadMarker = React.forwardRef(({ dayBreak, when, api, association }, ref) => {
|
||||
export const UnreadMarker = React.forwardRef(
|
||||
({ dayBreak, when, api, association }, ref) => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const idling = useIdlingState();
|
||||
const dismiss = useCallback(() => {
|
||||
@ -72,7 +73,7 @@ export const UnreadMarker = React.forwardRef(({ dayBreak, when, api, association
|
||||
}, [api, association]);
|
||||
|
||||
useEffect(() => {
|
||||
if(visible && !idling) {
|
||||
if (visible && !idling) {
|
||||
dismiss();
|
||||
}
|
||||
}, [visible, idling]);
|
||||
@ -96,7 +97,9 @@ export const UnreadMarker = React.forwardRef(({ dayBreak, when, api, association
|
||||
</VisibilitySensor>
|
||||
<Rule borderColor='lightBlue' />
|
||||
</Row>
|
||||
)});
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
interface ChatMessageProps {
|
||||
msg: Post;
|
||||
@ -126,8 +129,7 @@ class ChatMessage extends Component<ChatMessageProps> {
|
||||
this.divRef = React.createRef();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
}
|
||||
componentDidMount() {}
|
||||
|
||||
render() {
|
||||
const {
|
||||
@ -146,7 +148,7 @@ class ChatMessage extends Component<ChatMessageProps> {
|
||||
history,
|
||||
api,
|
||||
highlighted,
|
||||
fontSize,
|
||||
fontSize
|
||||
} = this.props;
|
||||
|
||||
let { renderSigil } = this.props;
|
||||
@ -170,7 +172,6 @@ class ChatMessage extends Component<ChatMessageProps> {
|
||||
.unix(msg['time-sent'] / 1000)
|
||||
.format(renderSigil ? 'h:mm A' : 'h:mm');
|
||||
|
||||
|
||||
const messageProps = {
|
||||
msg,
|
||||
timestamp,
|
||||
@ -183,7 +184,7 @@ class ChatMessage extends Component<ChatMessageProps> {
|
||||
api,
|
||||
scrollWindow,
|
||||
highlighted,
|
||||
fontSize,
|
||||
fontSize
|
||||
};
|
||||
|
||||
const unreadContainerStyle = {
|
||||
@ -204,11 +205,11 @@ class ChatMessage extends Component<ChatMessageProps> {
|
||||
) : null}
|
||||
{renderSigil ? (
|
||||
<>
|
||||
<MessageAuthor pb={'2px'} {...messageProps} />
|
||||
<Message pl={5} pr={4} {...messageProps} />
|
||||
<MessageAuthor pb={1} {...messageProps} />
|
||||
<Message pl={'44px'} pr={4} {...messageProps} />
|
||||
</>
|
||||
) : (
|
||||
<Message pl={5} pr={4} timestampHover {...messageProps} />
|
||||
<Message pl={'44px'} pr={4} timestampHover {...messageProps} />
|
||||
)}
|
||||
<Box style={unreadContainerStyle}>
|
||||
{isLastRead ? (
|
||||
@ -226,7 +227,9 @@ class ChatMessage extends Component<ChatMessageProps> {
|
||||
}
|
||||
}
|
||||
|
||||
export default React.forwardRef((props, ref) => <ChatMessage {...props} innerRef={ref} />);
|
||||
export default React.forwardRef((props, ref) => (
|
||||
<ChatMessage {...props} innerRef={ref} />
|
||||
));
|
||||
|
||||
export const MessageAuthor = ({
|
||||
timestamp,
|
||||
@ -239,9 +242,9 @@ export const MessageAuthor = ({
|
||||
}) => {
|
||||
const osDark = useLocalState((state) => state.dark);
|
||||
|
||||
const theme = useSettingsState(s => s.display.theme);
|
||||
const theme = useSettingsState((s) => s.display.theme);
|
||||
const dark = theme === 'dark' || (theme === 'auto' && osDark);
|
||||
const contacts = useContactState(state => state.contacts);
|
||||
const contacts = useContactState((state) => state.contacts);
|
||||
|
||||
const datestamp = moment
|
||||
.unix(msg['time-sent'] / 1000)
|
||||
@ -291,19 +294,30 @@ export const MessageAuthor = ({
|
||||
display='inline-block'
|
||||
style={{ objectFit: 'cover' }}
|
||||
src={contact.avatar}
|
||||
height={16}
|
||||
width={16}
|
||||
height={24}
|
||||
width={24}
|
||||
borderRadius={1}
|
||||
/>
|
||||
) : (
|
||||
<Box
|
||||
width={24}
|
||||
height={24}
|
||||
display='flex'
|
||||
justifyContent='center'
|
||||
alignItems='center'
|
||||
backgroundColor={color}
|
||||
borderRadius={1}
|
||||
>
|
||||
<Sigil
|
||||
ship={msg.author}
|
||||
size={16}
|
||||
size={12}
|
||||
display='block'
|
||||
color={color}
|
||||
classes={sigilClass}
|
||||
icon
|
||||
padding={2}
|
||||
padding={0}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
return (
|
||||
<Box display='flex' alignItems='center' {...rest}>
|
||||
@ -311,9 +325,9 @@ export const MessageAuthor = ({
|
||||
onClick={() => {
|
||||
setShowOverlay(true);
|
||||
}}
|
||||
height={16}
|
||||
height={24}
|
||||
pr={2}
|
||||
pl={2}
|
||||
pl={'12px'}
|
||||
cursor='pointer'
|
||||
position='relative'
|
||||
>
|
||||
@ -340,10 +354,10 @@ export const MessageAuthor = ({
|
||||
pt={1}
|
||||
pb={1}
|
||||
display='flex'
|
||||
alignItems='center'
|
||||
alignItems='baseline'
|
||||
>
|
||||
<Text
|
||||
fontSize={0}
|
||||
fontSize={1}
|
||||
mr={2}
|
||||
flexShrink={0}
|
||||
mono={nameMono}
|
||||
@ -385,13 +399,15 @@ export const Message = ({
|
||||
...rest
|
||||
}) => {
|
||||
const { hovering, bind } = useHovering();
|
||||
const contacts = useContactState(state => state.contacts);
|
||||
const contacts = useContactState((state) => state.contacts);
|
||||
return (
|
||||
<Box position='relative' {...rest}>
|
||||
{timestampHover ? (
|
||||
<Text
|
||||
display={hovering ? 'block' : 'none'}
|
||||
position='absolute'
|
||||
width='40px'
|
||||
textAlign='center'
|
||||
left='0'
|
||||
top='3px'
|
||||
fontSize={0}
|
||||
@ -454,7 +470,7 @@ export const Message = ({
|
||||
</Box>
|
||||
);
|
||||
case 'mention':
|
||||
const first = (i) => (i === 0);
|
||||
const first = (i) => i === 0;
|
||||
return (
|
||||
<Mention
|
||||
key={i}
|
||||
|
Loading…
Reference in New Issue
Block a user