mirror of
https://github.com/urbit/shrub.git
synced 2024-12-11 11:02:25 +03:00
Merge branch 'next/groups' into groups/embed-fix
This commit is contained in:
commit
00de041625
@ -34,7 +34,10 @@ export const ProviderLink = ({
|
||||
>
|
||||
<Avatar size={size} {...provider} />
|
||||
<div className="flex-1 text-black">
|
||||
<p className="font-mono">{provider.nickname || <ShipName name={provider.shipName} />}</p>
|
||||
<div className="flex font-mono space-x-4">
|
||||
<ShipName name={provider.shipName} />
|
||||
<span className="text-gray-500">{provider.nickname}</span>
|
||||
</div>
|
||||
{provider.status && size === 'default' && <p className="font-normal">{provider.status}</p>}
|
||||
</div>
|
||||
</Link>
|
||||
|
@ -103,10 +103,8 @@ export const Leap = React.forwardRef(
|
||||
(value: string) => {
|
||||
const onlySymbols = !value.match(/[\w]/g);
|
||||
const normValue = normalizeMatchString(value, onlySymbols);
|
||||
return matches.find(
|
||||
(m) =>
|
||||
(m.display && normalizeMatchString(m.display, onlySymbols).startsWith(normValue)) ||
|
||||
normalizeMatchString(m.value, onlySymbols).startsWith(normValue)
|
||||
return matches.find((m) =>
|
||||
normalizeMatchString(m.value, onlySymbols).startsWith(normValue)
|
||||
);
|
||||
},
|
||||
[matches]
|
||||
@ -141,7 +139,7 @@ export const Leap = React.forwardRef(
|
||||
const value = input.value.trim();
|
||||
const isDeletion = (e.nativeEvent as InputEvent).inputType === 'deleteContentBackward';
|
||||
const inputMatch = getMatch(value);
|
||||
const matchValue = inputMatch?.display || inputMatch?.value;
|
||||
const matchValue = inputMatch?.value;
|
||||
|
||||
if (matchValue && inputRef.current && !isDeletion) {
|
||||
inputRef.current.value = matchValue;
|
||||
@ -207,8 +205,8 @@ export const Leap = React.forwardRef(
|
||||
|
||||
const currentIndex = selectedMatch
|
||||
? matches.findIndex((m) => {
|
||||
const matchValue = m.display || m.value;
|
||||
const searchValue = selectedMatch.display || selectedMatch.value;
|
||||
const matchValue = m.value;
|
||||
const searchValue = selectedMatch.value;
|
||||
return matchValue === searchValue;
|
||||
})
|
||||
: 0;
|
||||
@ -216,9 +214,8 @@ export const Leap = React.forwardRef(
|
||||
const index = (unsafeIndex + matches.length) % matches.length;
|
||||
|
||||
const newMatch = matches[index];
|
||||
const matchValue = newMatch.display || newMatch.value;
|
||||
useLeapStore.setState({
|
||||
rawInput: matchValue,
|
||||
rawInput: newMatch.value,
|
||||
// searchInput: matchValue,
|
||||
selectedMatch: newMatch
|
||||
});
|
||||
@ -227,7 +224,6 @@ export const Leap = React.forwardRef(
|
||||
[selection, rawInput, match, matches, selectedMatch]
|
||||
);
|
||||
|
||||
|
||||
return (
|
||||
<div className="relative z-50 w-full">
|
||||
<form
|
||||
@ -257,7 +253,7 @@ export const Leap = React.forwardRef(
|
||||
type="text"
|
||||
ref={inputRef}
|
||||
placeholder={selection ? '' : 'Search'}
|
||||
className="flex-1 w-full h-full px-2 h4 text-base rounded-full bg-transparent outline-none"
|
||||
className="flex-1 w-full h-full px-2 text-base bg-transparent rounded-full outline-none h4"
|
||||
value={rawInput}
|
||||
onClick={toggleSearch}
|
||||
onFocus={onFocus}
|
||||
@ -266,14 +262,14 @@ export const Leap = React.forwardRef(
|
||||
autoComplete="off"
|
||||
aria-autocomplete="both"
|
||||
aria-controls={dropdown}
|
||||
aria-activedescendant={selectedMatch?.display || selectedMatch?.value}
|
||||
aria-activedescendant={selectedMatch?.value}
|
||||
/>
|
||||
) : null}
|
||||
</form>
|
||||
{menu === 'search' && (
|
||||
<Link
|
||||
to="/"
|
||||
className="absolute top-1/2 right-2 flex-none circle-button w-8 h-8 text-gray-400 bg-gray-50 default-ring -translate-y-1/2"
|
||||
className="absolute flex-none w-8 h-8 text-gray-400 top-1/2 right-2 circle-button bg-gray-50 default-ring -translate-y-1/2"
|
||||
onClick={() => select(null)}
|
||||
>
|
||||
<Cross className="w-3 h-3 fill-current" />
|
||||
|
@ -19,7 +19,7 @@
|
||||
"@tlon/indigo-light": "^1.0.7",
|
||||
"@tlon/indigo-react": "^1.2.27",
|
||||
"@tlon/sigil-js": "^1.4.3",
|
||||
"@urbit/api": "^2.1.0",
|
||||
"@urbit/api": "^2.1.1",
|
||||
"@urbit/http-api": "^2.1.0",
|
||||
"any-ascii": "^0.1.7",
|
||||
"aws-sdk": "^2.830.0",
|
||||
|
@ -40,7 +40,7 @@ export async function bootstrapApi() {
|
||||
useLocalState.setState({ subscription: 'connected' });
|
||||
};
|
||||
|
||||
await useMetadataState.getState().initialize(airlock);
|
||||
useMetadataState.getState().initialize(airlock);
|
||||
|
||||
const subs = [
|
||||
useGroupState,
|
||||
|
@ -34,7 +34,8 @@ const useStorage = ({ accept = '*' } = { accept: '*' }): IuseStorage => {
|
||||
}
|
||||
client.current = new S3Client({
|
||||
credentials: s3.credentials,
|
||||
endpoint: s3.credentials.endpoint
|
||||
endpoint: s3.credentials.endpoint,
|
||||
signatureVersion: 'v4'
|
||||
});
|
||||
}
|
||||
}, [gcp.token, s3.credentials]);
|
||||
|
@ -11,8 +11,7 @@ export function getTitleFromWorkspace(
|
||||
case 'messages':
|
||||
return 'Messages';
|
||||
case 'group':
|
||||
const association = associations.groups[workspace.group];
|
||||
return association?.metadata?.title || '';
|
||||
return associations.groups[workspace.group]?.metadata?.title || 'Groups';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { acceptDm, cite, Content, declineDm, deSig, Post } from '@urbit/api';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import Helmet from 'react-helmet';
|
||||
import _ from 'lodash';
|
||||
import bigInt from 'big-integer';
|
||||
import { Box, Row, Col, Text, Center } from '@tlon/indigo-react';
|
||||
@ -49,6 +50,21 @@ function quoteReply(post: Post) {
|
||||
return `${reply}\n\n~${post.author}:`;
|
||||
}
|
||||
|
||||
export function DmHelmet(props: DmHelmetProps) {
|
||||
const { ship } = props;
|
||||
const hark = useHarkDm(ship);
|
||||
const unreadCount = hark.count;
|
||||
const contact = useContact(ship);
|
||||
const { hideNicknames } = useSettingsState(selectCalmState);
|
||||
const showNickname = !hideNicknames && Boolean(contact);
|
||||
const nickname = showNickname ? contact!.nickname : cite(ship) ?? ship;
|
||||
return(
|
||||
<Helmet defer={false}>
|
||||
<title>{unreadCount ? `(${String(unreadCount)}) ` : ''}{ nickname }</title>
|
||||
</Helmet>
|
||||
);
|
||||
}
|
||||
|
||||
export function DmResource(props: DmResourceProps) {
|
||||
const { ship } = props;
|
||||
const dm = useDM(ship);
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Icon,
|
||||
Center,
|
||||
Row,
|
||||
Text,
|
||||
Col,
|
||||
@ -39,7 +38,7 @@ export interface LinkBlockItemProps {
|
||||
}
|
||||
|
||||
export function LinkBlockItem(props: LinkBlockItemProps & CenterProps) {
|
||||
const { node, summary, size, m, border = 1, objectFit, ...rest } = props;
|
||||
const { node, summary, m, border = 1, objectFit, ...rest } = props;
|
||||
const { post, children } = node;
|
||||
const { contents, index, author } = post;
|
||||
|
||||
@ -66,70 +65,69 @@ export function LinkBlockItem(props: LinkBlockItemProps & CenterProps) {
|
||||
history.push(`${pathname}/index${index}${search}`);
|
||||
};
|
||||
return (
|
||||
<Center
|
||||
<Box
|
||||
onClick={onClick}
|
||||
position="relative"
|
||||
m={m}
|
||||
border={border}
|
||||
borderColor="lightGray"
|
||||
position="relative"
|
||||
borderRadius="1"
|
||||
height={size}
|
||||
width={size}
|
||||
m={m}
|
||||
maxHeight="100%"
|
||||
{...rest}
|
||||
{...bind}
|
||||
>
|
||||
<AsyncFallback fallback={<RemoteContentEmbedFallback url={url} />}>
|
||||
{isReference ? (
|
||||
summary ? (
|
||||
<RemoteContentPermalinkEmbed
|
||||
reference={content[0] as ReferenceContent}
|
||||
/>
|
||||
) : (
|
||||
<PermalinkEmbed
|
||||
link={referenceToPermalink(content[0] as ReferenceContent).link}
|
||||
transcluded={0}
|
||||
/>
|
||||
)
|
||||
) : isImage ? (
|
||||
<RemoteContentImageEmbed
|
||||
url={url}
|
||||
tall
|
||||
stretch
|
||||
objectFit={objectFit ? objectFit : "cover"}
|
||||
/>
|
||||
) : isAudio ? (
|
||||
<AudioPlayer title={title} url={url} />
|
||||
) : isOembed ? (
|
||||
<RemoteContentOembed tall={!summary} renderUrl={false} url={url} thumbnail={summary} oembed={oembed} />
|
||||
) : (
|
||||
<RemoteContentEmbedFallback url={url} />
|
||||
)}
|
||||
</AsyncFallback>
|
||||
<Box
|
||||
backgroundColor="white"
|
||||
display={summary && hovering ? 'block' : 'none'}
|
||||
width="100%"
|
||||
height="64px"
|
||||
position="absolute"
|
||||
left="0"
|
||||
bottom="0"
|
||||
>
|
||||
<Col width="100%" height="100%" p="2" justifyContent="space-between">
|
||||
<Row justifyContent="space-between" width="100%">
|
||||
<Text textOverflow="ellipsis" whiteSpace="nowrap" overflow="hidden">
|
||||
{title}
|
||||
</Text>
|
||||
<Row gapX="1" alignItems="center">
|
||||
<Icon icon="Chat" color="black" />
|
||||
<Text>{children.size}</Text>
|
||||
<Col height="100%" justifyContent="center" alignItems="center">
|
||||
<AsyncFallback fallback={<RemoteContentEmbedFallback url={url} />}>
|
||||
{isReference ? (
|
||||
summary ? (
|
||||
<RemoteContentPermalinkEmbed
|
||||
reference={content[0] as ReferenceContent}
|
||||
/>
|
||||
) : (
|
||||
<PermalinkEmbed
|
||||
link={referenceToPermalink(content[0] as ReferenceContent).link}
|
||||
transcluded={0}
|
||||
/>
|
||||
)
|
||||
) : isImage ? (
|
||||
<RemoteContentImageEmbed
|
||||
url={url}
|
||||
tall
|
||||
stretch
|
||||
objectFit={objectFit ? objectFit : "cover"}
|
||||
/>
|
||||
) : isAudio ? (
|
||||
<AudioPlayer title={title} url={url} />
|
||||
) : isOembed ? (
|
||||
<RemoteContentOembed tall={!summary} renderUrl={false} url={url} thumbnail={summary} oembed={oembed} />
|
||||
) : (
|
||||
<RemoteContentEmbedFallback url={url} />
|
||||
)}
|
||||
</AsyncFallback>
|
||||
<Box
|
||||
backgroundColor="white"
|
||||
display={summary && hovering ? 'block' : 'none'}
|
||||
width="100%"
|
||||
height="64px"
|
||||
position="absolute"
|
||||
left="0"
|
||||
bottom="0"
|
||||
>
|
||||
<Col width="100%" height="100%" p="2" justifyContent="space-between">
|
||||
<Row justifyContent="space-between" width="100%">
|
||||
<Text textOverflow="ellipsis" whiteSpace="nowrap" overflow="hidden">
|
||||
{title}
|
||||
</Text>
|
||||
<Row gapX="1" alignItems="center">
|
||||
<Icon icon="Chat" color="black" />
|
||||
<Text>{children.size}</Text>
|
||||
</Row>
|
||||
</Row>
|
||||
</Row>
|
||||
<Row width="100%">
|
||||
<Author ship={author} date={post['time-sent']} showImage></Author>
|
||||
</Row>
|
||||
</Col>
|
||||
</Box>
|
||||
</Center>
|
||||
<Row width="100%">
|
||||
<Author ship={author} date={post['time-sent']} showImage></Author>
|
||||
</Row>
|
||||
</Col>
|
||||
</Box>
|
||||
</Col>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Col, Row, RowProps } from '@tlon/indigo-react';
|
||||
import { Center, Col, Row, RowProps } from '@tlon/indigo-react';
|
||||
import { Association, GraphNode, markEachAsRead, TextContent, UrlContent } from '@urbit/api';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useGroup } from '~/logic/state/group';
|
||||
@ -27,21 +27,13 @@ export function LinkDetail(props: LinkDetailProps) {
|
||||
return (
|
||||
/* @ts-ignore indio props?? */
|
||||
<Row height="100%" width="100%" flexDirection={['column', 'column', 'row']} {...rest}>
|
||||
<LinkBlockItem
|
||||
minWidth="0"
|
||||
minHeight="0"
|
||||
height={["50%", "50%", "100%"]}
|
||||
width={["100%", "100%", "calc(100% - 350px)"]}
|
||||
flexGrow={0}
|
||||
border={0}
|
||||
node={node}
|
||||
objectFit="contain"
|
||||
/>
|
||||
<Center flex="3 1 75%" overflowY="scroll" >
|
||||
<LinkBlockItem maxHeight="100%" border={0} node={node} objectFit="contain" />
|
||||
</Center>
|
||||
<Col
|
||||
minHeight="0"
|
||||
flexShrink={1}
|
||||
width={['100%', '100%', '350px']}
|
||||
flexGrow={0}
|
||||
flex="1 25%"
|
||||
maxWidth={['auto', 'auto', '45ch']}
|
||||
maxHeight={['50%', '50%', 'unset']}
|
||||
gapY={[2,4]}
|
||||
borderLeft={[0, 0, 1]}
|
||||
borderTop={[1, 1, 0]}
|
||||
|
@ -90,33 +90,33 @@ export function EditProfile(props: any): ReactElement {
|
||||
|
||||
const onSubmit = async (values: any, actions: any) => {
|
||||
try {
|
||||
Object.keys(values).forEach((key) => {
|
||||
for (const key in values) {
|
||||
const newValue = key !== 'color' ? values[key] : uxToHex(values[key]);
|
||||
if (newValue !== contact[key]) {
|
||||
if (key === 'isPublic') {
|
||||
airlock.poke(setPublic(newValue));
|
||||
return;
|
||||
} else if (key === 'groups') {
|
||||
const toRemove: string[] = _.difference(
|
||||
contact?.groups || [],
|
||||
newValue
|
||||
);
|
||||
const toAdd: string[] = _.difference(
|
||||
newValue,
|
||||
contact?.groups || []
|
||||
);
|
||||
toRemove.forEach(e =>
|
||||
airlock.poke(editContact(ship, { 'remove-group': resourceFromPath(e) }))
|
||||
);
|
||||
toAdd.forEach(e =>
|
||||
airlock.poke(editContact(ship, { 'add-group': resourceFromPath(e) }))
|
||||
);
|
||||
} else if (key !== 'last-updated' && key !== 'isPublic') {
|
||||
airlock.poke(editContact(ship, { [key]: newValue }));
|
||||
return;
|
||||
if (newValue === contact[key] || key === 'last-updated') {
|
||||
continue;
|
||||
} else if (key === 'isPublic') {
|
||||
await airlock.poke(setPublic(newValue));
|
||||
} else if (key === 'groups') {
|
||||
const toRemove: string[] = _.difference(
|
||||
contact?.groups || [],
|
||||
newValue
|
||||
);
|
||||
const toAdd: string[] = _.difference(
|
||||
newValue,
|
||||
contact?.groups || []
|
||||
);
|
||||
for (const i in toRemove) {
|
||||
const group = resourceFromPath(toRemove[i]);
|
||||
await airlock.poke(editContact(ship, { 'remove-group': group }));
|
||||
}
|
||||
for (const i in toAdd) {
|
||||
const group = resourceFromPath(toAdd[i]);
|
||||
await airlock.poke(editContact(ship, { 'add-group': group }));
|
||||
}
|
||||
} else {
|
||||
await airlock.poke(editContact(ship, { [key]: newValue }));
|
||||
}
|
||||
});
|
||||
}
|
||||
history.push(`/~profile/${ship}`);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
@ -3,7 +3,7 @@ import moment from 'moment';
|
||||
import React, { ReactElement, ReactNode } from 'react';
|
||||
import { Sigil } from '~/logic/lib/sigil';
|
||||
import { useCopy } from '~/logic/lib/useCopy';
|
||||
import { cite, uxToHex } from '~/logic/lib/util';
|
||||
import { cite, deSig, uxToHex } from '~/logic/lib/util';
|
||||
import { useContact } from '~/logic/state/contact';
|
||||
import { useDark } from '~/logic/state/join';
|
||||
import useSettingsState, { selectCalmState, useShowNickname } from '~/logic/state/settings';
|
||||
@ -52,7 +52,7 @@ function Author(props: AuthorProps & PropFunc<typeof Box>): ReactElement {
|
||||
const { hideAvatars } = useSettingsState(selectCalmState);
|
||||
const name = showNickname && contact ? contact.nickname : cite(ship);
|
||||
const stamp = moment(date);
|
||||
const { copyDisplay, doCopy } = useCopy(`~${ship}`, name);
|
||||
const { copyDisplay, doCopy } = useCopy(`~${deSig(ship)}`, name);
|
||||
|
||||
const sigil = fullNotIcon ? (
|
||||
<Sigil ship={ship} size={size} color={color} padding={sigilPadding} />
|
||||
|
@ -97,6 +97,7 @@ export function RemoteContentImageEmbed(
|
||||
objectFit="cover"
|
||||
borderRadius={2}
|
||||
onError={onError}
|
||||
style={{ imageRendering: '-webkit-optimize-contrast' }}
|
||||
{...props}
|
||||
/>
|
||||
</Box>
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
} from 'react-router-dom';
|
||||
import { useShortcut } from '~/logic/state/settings';
|
||||
import { useLocalStorageState } from '~/logic/lib/useLocalStorageState';
|
||||
import { getGroupFromWorkspace } from '~/logic/lib/workspace';
|
||||
import { getGroupFromWorkspace, getTitleFromWorkspace } from '~/logic/lib/workspace';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import useHarkState from '~/logic/state/hark';
|
||||
import useMetadataState from '~/logic/state/metadata';
|
||||
@ -22,7 +22,7 @@ import { Skeleton } from './Skeleton';
|
||||
import { EmptyGroupHome } from './Home/EmptyGroupHome';
|
||||
import { Join } from './Join/Join';
|
||||
import { Resource } from './Resource';
|
||||
import { DmResource } from '~/views/apps/chat/DmResource';
|
||||
import { DmResource, DmHelmet } from '~/views/apps/chat/DmResource';
|
||||
import { UnjoinedResource } from '~/views/components/UnjoinedResource';
|
||||
import { NewChannel } from './NewChannel';
|
||||
import { GroupHome } from './Home/GroupHome';
|
||||
@ -126,16 +126,18 @@ export function GroupsPane(props: GroupsPaneProps) {
|
||||
const { ship } = match.params as Record<string, string>;
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
mobileHide
|
||||
recentGroups={recentGroups}
|
||||
selected={ship}
|
||||
{...props}
|
||||
baseUrl={match.path}
|
||||
> <DmResource ship={ship} />
|
||||
|
||||
</Skeleton>
|
||||
<>
|
||||
<DmHelmet ship={ship} />
|
||||
<Skeleton
|
||||
mobileHide
|
||||
recentGroups={recentGroups}
|
||||
selected={ship}
|
||||
{...props}
|
||||
baseUrl={match.path}
|
||||
> <DmResource ship={ship} />
|
||||
|
||||
</Skeleton>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
@ -180,7 +182,7 @@ export function GroupsPane(props: GroupsPaneProps) {
|
||||
const appPath = `/ship/${host}/${name}`;
|
||||
const association = associations.graph[appPath];
|
||||
const resourceUrl = `${baseUrl}/join/${app}${appPath}`;
|
||||
let title = groupAssociation?.metadata?.title ?? 'Groups';
|
||||
let title = getTitleFromWorkspace(associations, workspace);
|
||||
|
||||
if (!association) {
|
||||
return <Loading />;
|
||||
@ -252,7 +254,7 @@ export function GroupsPane(props: GroupsPaneProps) {
|
||||
render={(routeProps) => {
|
||||
const shouldHideSidebar =
|
||||
routeProps.location.pathname.includes('/feed');
|
||||
const title = groupAssociation?.metadata?.title ?? 'Groups';
|
||||
const title = getTitleFromWorkspace(associations, workspace);
|
||||
return (
|
||||
<>
|
||||
<Helmet defer={false}>
|
||||
|
@ -10,16 +10,17 @@
|
||||
[%2 network:zero:store]
|
||||
[%3 network:one:store]
|
||||
[%4 network:store]
|
||||
state-5
|
||||
[%5 network:store]
|
||||
state-6
|
||||
==
|
||||
::
|
||||
+$ state-5 [%5 network:store]
|
||||
::-
|
||||
+$ state-6 [%6 network:store]
|
||||
++ orm orm:store
|
||||
++ orm-log orm-log:store
|
||||
++ mar %graph-update-3
|
||||
--
|
||||
::
|
||||
=| state-5
|
||||
=| state-6
|
||||
=* state -
|
||||
::
|
||||
%- agent:dbug
|
||||
@ -81,7 +82,21 @@
|
||||
(gas:orm-log ~ [now.bowl logged-update] ~)
|
||||
==
|
||||
::
|
||||
%5 [cards this(state old)]
|
||||
%5
|
||||
%_ $
|
||||
-.old %6
|
||||
::
|
||||
update-logs.old
|
||||
%- ~(rut by update-logs.old)
|
||||
|= [=resource:store =update-log:store]
|
||||
^- update-log:store
|
||||
?: =(our.bowl entity.resource)
|
||||
update-log
|
||||
%+ gas:orm-log *update-log:store
|
||||
(scag 2 (tap:orm-log update-log))
|
||||
==
|
||||
::
|
||||
%6 [cards this(state old)]
|
||||
==
|
||||
::
|
||||
++ on-watch
|
||||
@ -138,6 +153,15 @@
|
||||
%tags ~|('cannot send %tags as poke' !!)
|
||||
%tag-queries ~|('cannot send %tag-queries as poke' !!)
|
||||
==
|
||||
++ put-update-log
|
||||
|= [=resource:store =update-log:store =time =logged-update:store]
|
||||
^- update-log:store
|
||||
?: =(our.bowl entity.resource)
|
||||
(put:orm-log update-log time logged-update)
|
||||
%+ gas:orm-log *update-log:store
|
||||
:~ (need (pry:orm-log update-log))
|
||||
[time logged-update]
|
||||
==
|
||||
::
|
||||
++ add-graph
|
||||
|= $: =time
|
||||
@ -194,7 +218,7 @@
|
||||
?> is-valid
|
||||
=/ =update-log:store (~(got by update-logs) resource)
|
||||
=. update-log
|
||||
(put:orm-log update-log time [time [%add-nodes resource nodes]])
|
||||
(put-update-log resource update-log time [time %add-nodes resource nodes])
|
||||
::
|
||||
:- (give [/updates]~ [%add-nodes resource nodes])
|
||||
%_ state
|
||||
@ -332,7 +356,9 @@
|
||||
(~(got by graphs) resource)
|
||||
=/ =update-log:store (~(got by update-logs) resource)
|
||||
=. update-log
|
||||
(put:orm-log update-log time [time [%remove-posts resource indices]])
|
||||
%^ put-update-log resource
|
||||
update-log
|
||||
[time time %remove-posts resource indices]
|
||||
:- (give [/updates]~ [%remove-posts resource indices])
|
||||
%_ state
|
||||
update-logs (~(put by update-logs) resource update-log)
|
||||
@ -419,8 +445,9 @@
|
||||
(~(got by graphs) resource)
|
||||
=/ =update-log:store (~(got by update-logs) resource)
|
||||
=. update-log
|
||||
(put:orm-log update-log time [time [%add-signatures uid signatures]])
|
||||
::
|
||||
%^ put-update-log resource
|
||||
update-log
|
||||
[time time %add-signatures uid signatures]
|
||||
:- (give [/updates]~ [%add-signatures uid signatures])
|
||||
%_ state
|
||||
update-logs (~(put by update-logs) resource update-log)
|
||||
@ -467,9 +494,9 @@
|
||||
(~(got by graphs) resource)
|
||||
=/ =update-log:store (~(got by update-logs) resource)
|
||||
=. update-log
|
||||
%^ put:orm-log update-log
|
||||
time
|
||||
[time [%remove-signatures uid signatures]]
|
||||
%^ put-update-log resource
|
||||
update-log
|
||||
[time time %remove-signatures uid signatures]
|
||||
::
|
||||
:- (give [/updates]~ [%remove-signatures uid signatures])
|
||||
%_ state
|
||||
|
@ -1,10 +1,10 @@
|
||||
:~ title+'Groups'
|
||||
info+'A suite of applications to communicate on Urbit'
|
||||
color+0xee.5432
|
||||
glob-http+['https://bootstrap.urbit.org/glob-0v6.v8tfj.52ls5.409gr.rnt3f.090hm.glob' 0v6.v8tfj.52ls5.409gr.rnt3f.090hm]
|
||||
glob-http+['https://bootstrap.urbit.org/glob-0v7.bmftr.90ktq.cma0h.da190.bs8b1.glob' 0v7.bmftr.90ktq.cma0h.da190.bs8b1]
|
||||
|
||||
base+'landscape'
|
||||
version+[1 0 10]
|
||||
version+[1 0 11]
|
||||
website+'https://tlon.io'
|
||||
license+'MIT'
|
||||
==
|
||||
|
@ -758,9 +758,9 @@
|
||||
--
|
||||
++ import
|
||||
|= [arc=* our=ship]
|
||||
^- (quip card:agent:gall [%5 network])
|
||||
^- (quip card:agent:gall [%6 network])
|
||||
|^
|
||||
=/ sty [%5 (remake-network ;;(tree-network +.arc))]
|
||||
=/ sty [%6 (remake-network ;;(tree-network +.arc))]
|
||||
:_ sty
|
||||
%+ turn ~(tap by graphs.sty)
|
||||
|= [rid=resource =marked-graph]
|
||||
|
@ -198,7 +198,7 @@ export const isWriter = (group: Group, resource: string, ship: string) => {
|
||||
if (typeof writers === 'undefined') {
|
||||
return true;
|
||||
} else {
|
||||
return writers.includes(ship) || admins.includes(ship);
|
||||
return [...writers].includes(ship) || admins.includes(ship);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@urbit/api",
|
||||
"version": "2.1.0",
|
||||
"version": "2.1.1",
|
||||
"description": "A library that provides bindings and types for Urbit's various userspace desks",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
Loading…
Reference in New Issue
Block a user