Merge branch 'release/next-js' of https://github.com/urbit/urbit into npm-packages

This commit is contained in:
Tyler Brown Cifu Shuster 2021-02-14 14:14:30 -08:00
commit 2b30227f0f
16 changed files with 111 additions and 95 deletions

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:f4b93e4d91e42c8444bb22447a0ae7d969ec552ba2d0f4b87a8dd20a41709d4e oid sha256:ec58605002fafbe6f3a5988fe1db4bd31e2fd40370b30e96db64a98c8f7da0ea
size 9345380 size 9474412

View File

@ -94,16 +94,18 @@
++ rolo ++ rolo
^- rolodex:store ^- rolodex:store
=/ ugroup (scry-group:grp resource) =/ ugroup (scry-group:grp resource)
=/ =rolodex:store
(scry-for:con rolodex:store /all)
%- ~(gas by *rolodex:store) %- ~(gas by *rolodex:store)
?~ ugroup ?~ ugroup
=/ c=(unit contact:store) (get-contact:con our.bowl) =/ c=(unit contact:store) (~(get by rolodex) our.bowl)
?~ c ?~ c
[our.bowl *contact:store]~ [our.bowl *contact:store]~
[our.bowl u.c]~ [our.bowl u.c]~
%+ murn ~(tap in (members:grp resource)) %+ murn ~(tap in (members:grp resource))
|= s=ship |= s=ship
^- (unit [ship contact:store]) ^- (unit [ship contact:store])
=/ c=(unit contact:store) (get-contact:con s) =/ c=(unit contact:store) (~(get by rolodex) s)
?~(c ~ `[s u.c]) ?~(c ~ `[s u.c])
-- --
:: ::

View File

@ -104,10 +104,18 @@
|= [rolo=rolodex:store is-public=?] |= [rolo=rolodex:store is-public=?]
^- (quip card _state) ^- (quip card _state)
=/ our-contact (~(got by rolodex) our.bowl) =/ our-contact (~(got by rolodex) our.bowl)
=. rolodex (~(uni by rolodex) rolo) =/ diff-rolo=rolodex:store
=. rolodex (~(put by rolodex) our.bowl our-contact) %- ~(gas by *rolodex:store)
:_ state(rolodex rolodex) %+ skim ~(tap in rolo)
(send-diff [%initial rolodex is-public] %.n) |= [=ship =contact:store]
?~ local-con=(~(get by rolodex) ship) %.y
(gth last-updated.contact last-updated.u.local-con)
=/ new-rolo=rolodex:store
(~(uni by rolodex) diff-rolo)
=. new-rolo (~(put by new-rolo) our.bowl our-contact)
?: =(new-rolo rolodex) `state
:_ state(rolodex new-rolo)
(send-diff [%initial new-rolo is-public] %.n)
:: ::
++ handle-add ++ handle-add
|= [=ship =contact:store] |= [=ship =contact:store]

View File

@ -5,7 +5,7 @@
/- glob /- glob
/+ default-agent, verb, dbug /+ default-agent, verb, dbug
|% |%
++ hash 0v3.t4lg5.84a6h.2bi2s.ni2p9.32uor ++ hash 0v7.iotki.j1ptb.mk9vm.borai.jfcr1
+$ state-0 [%0 hash=@uv glob=(unit (each glob:glob tid=@ta))] +$ state-0 [%0 hash=@uv glob=(unit (each glob:glob tid=@ta))]
+$ all-states +$ all-states
$% state-0 $% state-0

View File

@ -24,6 +24,6 @@
<div id="portal-root"></div> <div id="portal-root"></div>
<script src="/~landscape/js/channel.js"></script> <script src="/~landscape/js/channel.js"></script>
<script src="/~landscape/js/session.js"></script> <script src="/~landscape/js/session.js"></script>
<script src="/~landscape/js/bundle/index.dcdc4301b299cb03bad0.js"></script> <script src="/~landscape/js/bundle/index.096bb7cb32b754071b13.js"></script>
</body> </body>
</html> </html>

View File

@ -59,18 +59,16 @@ const edit = (json: ContactUpdate, state: S) => {
if (!field) { if (!field) {
return; return;
} }
const contact = state.contacts?.[ship];
const value = data['edit-field'][field];
if(!contact) {
return;
}
const value = data['edit-field'][field];
if(field === 'add-group') { if(field === 'add-group') {
contact.groups.push(value); state.contacts[ship].groups.push(value);
} else if (field === 'remove-group') { } else if (field === 'remove-group') {
contact.groups = contact.groups.filter(g => g !== value); state.contacts[ship].groups =
state.contacts[ship].groups.filter(g => g !== value);
} else { } else {
contact[field] = value; state.contacts[ship][field] = value;
} }
} }
}; };

View File

@ -80,52 +80,52 @@ export function ChatResource(props: ChatResourceProps) {
}, [station]); }, [station]);
const [showBanner, setShowBanner] = useState(false); const [showBanner, setShowBanner] = useState(false);
const [hasLoadedAllowed, setHasLoadedAllowed] = useState(false);
const [recipients, setRecipients] = useState([]); const [recipients, setRecipients] = useState([]);
const res = resourceFromPath(groupPath); const res = resourceFromPath(groupPath);
useEffect(() => { useEffect(() => {
(async () => { (async () => {
if (!res) { if (!res) { return; }
return; if (!group) { return; }
} if (group.hidden) {
if (!group) { const members = _.compact(await Promise.all(
return; Array.from(group.members)
} .map(s => {
if (group.hidden) { const ship = `~${s}`;
const members = _.compact(await Promise.all( if(s === window.ship) {
Array.from(group.members) return Promise.resolve(null);
.map((s) => { }
const ship = `~${s}`; return props.api.contacts.fetchIsAllowed(
if(s === window.ship) { `~${window.ship}`,
return Promise.resolve(null); 'personal',
} ship,
return props.api.contacts.fetchIsAllowed( true
`~${window.ship}`, ).then(isAllowed => {
'personal', return isAllowed ? null : ship;
ship, });
true })
).then((isAllowed) => { ));
return isAllowed ? null : ship;
}); if(members.length > 0) {
}) setShowBanner(true);
)); setRecipients(members);
} else {
setShowBanner(false);
}
if(members.length > 0) {
setShowBanner(true);
setRecipients(members);
} else { } else {
setShowBanner(false); const groupShared = await props.api.contacts.fetchIsAllowed(
`~${window.ship}`,
'personal',
res.ship,
true
);
setShowBanner(!groupShared);
} }
} else {
const groupShared = await props.api.contacts.fetchIsAllowed( setHasLoadedAllowed(true);
`~${window.ship}`,
'personal',
res.ship,
true
);
setShowBanner(!groupShared);
}
})(); })();
}, [groupPath]); }, [groupPath]);
@ -153,7 +153,10 @@ export function ChatResource(props: ChatResourceProps) {
history={props.history} history={props.history}
graph={graph} graph={graph}
unreadCount={unreadCount} unreadCount={unreadCount}
contacts={!showBanner ? contacts : modifiedContacts} contacts={
(!showBanner && hasLoadedAllowed) ?
contacts : modifiedContacts
}
association={props.association} association={props.association}
associations={props.associations} associations={props.associations}
groups={props.groups} groups={props.groups}
@ -168,9 +171,13 @@ export function ChatResource(props: ChatResourceProps) {
ref={chatInput} ref={chatInput}
api={props.api} api={props.api}
station={station} station={station}
ourContact={!showBanner ? ourContact : null} ourContact={
(!showBanner && hasLoadedAllowed) ? ourContact : null
}
envelopes={[]} envelopes={[]}
contacts={contacts} contacts={
(!showBanner && hasLoadedAllowed) ? contacts : modifiedContacts
}
onUnmount={appendUnsent} onUnmount={appendUnsent}
s3={props.s3} s3={props.s3}
placeholder="Message..." placeholder="Message..."

View File

@ -95,16 +95,8 @@ h2 {
font-family: "Inter", sans-serif; font-family: "Inter", sans-serif;
} }
.embed-container {
width: 100%;
height: 14rem;
}
.embed-container iframe { .embed-container iframe {
max-width: 24rem; max-width: 100%;
width: 100%;
height: 100%;
max-height: 26rem;
} }
.mh-16 { .mh-16 {

View File

@ -7,14 +7,15 @@ import {
Row, Row,
BaseImage, BaseImage,
Text Text
} from '@tlon/indigo-react'; } from "@tlon/indigo-react";
import RichText from '~/views/components/RichText'
import useLocalState from "~/logic/state/local";
import { Sigil } from '~/logic/lib/sigil'; import { Sigil } from '~/logic/lib/sigil';
import { ViewProfile } from './ViewProfile'; import { ViewProfile } from './ViewProfile';
import { EditProfile } from './EditProfile'; import { EditProfile } from './EditProfile';
import { SetStatusBarModal } from '~/views/components/SetStatusBarModal'; import { SetStatusBarModal } from '~/views/components/SetStatusBarModal';
import { uxToHex } from '~/logic/lib/util'; import { uxToHex } from '~/logic/lib/util';
import useLocalState from '~/logic/state/local';
import { useTutorialModal } from '~/views/components/useTutorialModal'; import { useTutorialModal } from '~/views/components/useTutorialModal';
export function Profile(props: any): ReactElement { export function Profile(props: any): ReactElement {
@ -61,8 +62,9 @@ export function Profile(props: any): ReactElement {
width="100%" width="100%"
> >
<Row alignItems="center" justifyContent="space-between"> <Row alignItems="center" justifyContent="space-between">
<Row>
{ship === `~${window.ship}` ? ( {ship === `~${window.ship}` ? (
<Row> <>
<Text <Text
py='2' py='2'
cursor='pointer' cursor='pointer'
@ -79,14 +81,12 @@ export function Profile(props: any): ReactElement {
ship={`~${window.ship}`} ship={`~${window.ship}`}
contact={contact} contact={contact}
/> />
</Row> </>
) : null} ) : null}
<Text maxWidth='18rem' overflowX='hidden' </Row>
textOverflow="ellipsis" <RichText mb='0' py='2' disableRemoteContent maxWidth='18rem' overflowX='hidden' textOverflow="ellipsis"
whiteSpace="nowrap" whiteSpace="nowrap"
overflow="hidden" display="inline-block" overflow="hidden" display="inline-block" verticalAlign="middle">{contact?.status ?? ""}</RichText>
verticalAlign="middle"
>{contact?.status ?? ''}</Text>
</Row> </Row>
<Row width="100%" height="300px"> <Row width="100%" height="300px">
{cover} {cover}

View File

@ -59,7 +59,7 @@ export function InviteItem(props: InviteItemProps) {
if (props.groups?.[resource]?.hidden) { if (props.groups?.[resource]?.hidden) {
const { metadata } = associations.graph[resource]; const { metadata } = associations.graph[resource];
if (name.startsWith('dm--')) { if (metadata?.module === 'chat') {
history.push(`/~landscape/messages/resource/${metadata.module}${resource}`); history.push(`/~landscape/messages/resource/${metadata.module}${resource}`);
} else { } else {
history.push(`/~landscape/home/resource/${metadata.module}${resource}`); history.push(`/~landscape/home/resource/${metadata.module}${resource}`);
@ -122,10 +122,7 @@ export function InviteItem(props: InviteItemProps) {
<JoinSkeleton status={status} gapY="3"> <JoinSkeleton status={status} gapY="3">
<Row py="1" alignItems="center"> <Row py="1" alignItems="center">
<Icon display="block" color="blue" icon="Bullet" mr="2" /> <Icon display="block" color="blue" icon="Bullet" mr="2" />
<Text mr="1">You are joining a DM with</Text> <Text mr="1">Joining direct message...</Text>
<Text mr="1" mono>
{cite('~hastuc-dibtux')}
</Text>
</Row> </Row>
</JoinSkeleton> </JoinSkeleton>
); );

View File

@ -14,6 +14,7 @@ import {
ColProps, ColProps,
Icon Icon
} from '@tlon/indigo-react'; } from '@tlon/indigo-react';
import RichText from './RichText';
import { withLocalState } from '~/logic/state/local'; import { withLocalState } from '~/logic/state/local';
import { ProfileStatus } from './ProfileStatus'; import { ProfileStatus } from './ProfileStatus';
@ -133,7 +134,7 @@ class ProfileOverlay extends PureComponent<ProfileOverlayProps, Record<string, n
> >
{img} {img}
</Box> </Box>
<Col alignItems="end" justifyContent="flex-end" overflow="hidden"> <Col alignItems="end" justifyContent="flex-end" overflow="hidden" minWidth='0'>
<Row width="100%" > <Row width="100%" >
<Text <Text
fontWeight='600' fontWeight='600'
@ -153,9 +154,12 @@ class ProfileOverlay extends PureComponent<ProfileOverlayProps, Record<string, n
contact={contact} contact={contact}
/> />
) : ( ) : (
<Text gray> <RichText display='inline-block' width='100%' minWidth='0' textOverflow='ellipsis'
overflow='hidden'
whiteSpace='pre'
lineHeight="tall" disableRemoteContent gray>
{contact?.status ? contact.status : ''} {contact?.status ? contact.status : ''}
</Text> </RichText>
) )
} }
</Col> </Col>

View File

@ -33,10 +33,10 @@ const RichText = React.memo(({ disableRemoteContent, ...props }) => (
videoShown: false, videoShown: false,
oembedShown: false oembedShown: false
} : null; } : null;
if (hasProvider(linkProps.href)) { if (!disableRemoteContent && hasProvider(linkProps.href)) {
return <RemoteContent className="mw-100" url={linkProps.href} />; return <RemoteContent className="mw-100" url={linkProps.href} />;
} }
return <BaseAnchor target='_blank' rel='noreferrer noopener' borderBottom='1px solid' remoteContentPolicy={remoteContentPolicy} {...linkProps}>{linkProps.children}</BaseAnchor>; return <BaseAnchor target='_blank' rel='noreferrer noopener' borderBottom='1px solid' remoteContentPolicy={remoteContentPolicy} {...linkProps}>{linkProps.children}</BaseAnchor>;
}, },
linkReference: (linkProps) => { linkReference: (linkProps) => {

View File

@ -107,7 +107,7 @@ const StatusBar = (props) => {
width="auto" width="auto"
alignY="top" alignY="top"
alignX="right" alignX="right"
flexShrink={0} flexShrink={'0'}
options={ options={
<Col <Col
mt='6' mt='6'

View File

@ -39,8 +39,10 @@ export function GroupsPane(props: GroupsPaneProps) {
const relativePath = (path: string) => baseUrl + path; const relativePath = (path: string) => baseUrl + path;
const groupPath = getGroupFromWorkspace(workspace); const groupPath = getGroupFromWorkspace(workspace);
const groupContacts = (groupPath && contacts[groupPath]) || undefined; const groupContacts = Object.assign({}, ...Array.from(groups?.[groupPath]?.members ?? []).filter(e => contacts[`~${e}`]).map(e => {
const rootIdentity = contacts?.['/~/default']?.[window.ship]; return {[e]: contacts[`~${e}`]};
})) || {};
const rootIdentity = contacts?.["/~/default"]?.[window.ship];
const groupAssociation = const groupAssociation =
(groupPath && associations.groups[groupPath]) || undefined; (groupPath && associations.groups[groupPath]) || undefined;
const group = (groupPath && groups[groupPath]) || undefined; const group = (groupPath && groups[groupPath]) || undefined;

View File

@ -101,7 +101,7 @@ export function NewChannel(props: NewChannelProps & RouteComponentProps): ReactE
await waiter(p => Boolean(p?.groups?.[`/ship/~${window.ship}/${resId}`])); await waiter(p => Boolean(p?.groups?.[`/ship/~${window.ship}/${resId}`]));
} }
actions.setStatus({ success: null }); actions.setStatus({ success: null });
const resourceUrl = parentPath(location.pathname); const resourceUrl = (location.pathname.includes("/messages")) ? "/~landscape/messages" : parentPath(location.pathname);
history.push( history.push(
`${resourceUrl}/resource/${moduleType}/ship/~${window.ship}/${resId}` `${resourceUrl}/resource/${moduleType}/ship/~${window.ship}/${resId}`
); );

View File

@ -31,10 +31,12 @@ import GlobalApi from '~/logic/api/global';
import { StatelessAsyncAction } from '~/views/components/StatelessAsyncAction'; import { StatelessAsyncAction } from '~/views/components/StatelessAsyncAction';
import useLocalState from '~/logic/state/local'; import useLocalState from '~/logic/state/local';
const TruncText = styled(Box)` const TruncText = styled(Text)`
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
display: inline-block;
min-width: 0;
`; `;
type Participant = Contact & { patp: string; pending: boolean }; type Participant = Contact & { patp: string; pending: boolean };
@ -55,8 +57,10 @@ function getParticipants(cs: Contacts, group: Group) {
patp, patp,
pending: false pending: false
})); }));
const members: Participant[] = _.map(Array.from(group.members), m => const members: Participant[] = _.map(
emptyContact(m, false) Array.from(group.members)
.filter(e => group?.policy?.invite?.pending ? !group.policy.invite.pending.has(e) : true), m =>
emptyContact(m, false)
); );
const allMembers = _.unionBy(contacts, members, 'patp'); const allMembers = _.unionBy(contacts, members, 'patp');
const pending: Participant[] = const pending: Participant[] =
@ -303,11 +307,13 @@ function Participant(props: {
return ( return (
<> <>
<Box>{avatar}</Box> <Box>{avatar}</Box>
<Col justifyContent="center" gapY="1" height="100%"> <Col justifyContent="center" gapY="1" height="100%" minWidth='0'>
{hasNickname && ( {hasNickname && (
<TruncText title={contact.nickname} maxWidth="85%" color="black"> <Row minWidth='0' flexShrink='1'>
<TruncText title={contact.nickname} color="black">
{contact.nickname} {contact.nickname}
</TruncText> </TruncText>
</Row>
)} )}
<Text title={contact.patp} color="gray" fontFamily="mono"> <Text title={contact.patp} color="gray" fontFamily="mono">
{cite(contact.patp)} {cite(contact.patp)}