mirror of
https://github.com/urbit/shrub.git
synced 2024-12-25 04:52:06 +03:00
interface: fix misc bugs
This commit is contained in:
parent
a49399269b
commit
d593561b0f
@ -18,11 +18,11 @@
|
||||
"display": "standalone",
|
||||
"background_color": "%23FFFFFF",
|
||||
"theme_color": "%23000000"}' />
|
||||
<script src="/apps/landscape/desk.js"></script>
|
||||
<script src="/session.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<div id="portal-root"></div>
|
||||
<script src="/apps/landscape/desk.js"></script>
|
||||
<script src="/session.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -107,7 +107,7 @@ function updateNotificationStats(state: HarkState, place: HarkPlace, f: (s: Hark
|
||||
}
|
||||
|
||||
function seenIndex(json: any, state: HarkState): HarkState {
|
||||
const data = _.get(json, 'seen-index');
|
||||
const data = _.get(json, 'saw-place');
|
||||
if(data) {
|
||||
updateNotificationStats(state, data, s => ({ last: Date.now() }));
|
||||
}
|
||||
@ -154,6 +154,7 @@ function unreadEach(json: any, state: HarkState): HarkState {
|
||||
function allStats(json: any, state: HarkState): HarkState {
|
||||
if('all-stats' in json) {
|
||||
const data = json['all-stats'];
|
||||
console.log(data);
|
||||
data.forEach(({ place, stats }) => {
|
||||
state.unreads[place.path] = stats;
|
||||
});
|
||||
|
@ -4,7 +4,6 @@ import {
|
||||
markCountAsRead,
|
||||
Notification,
|
||||
NotificationGraphConfig,
|
||||
readNote,
|
||||
Unreads
|
||||
} from '@urbit/api';
|
||||
import { Poke } from '@urbit/http-api';
|
||||
@ -132,9 +131,8 @@ export function useHarkDm(ship: string) {
|
||||
return useHarkState(
|
||||
useCallback(
|
||||
(s) => {
|
||||
return s.unreads[`/graph/~${window.ship}/dm-inbox`]?.[
|
||||
`/${patp2dec(ship)}`
|
||||
] || emptyStats();
|
||||
const key = `/graph/~${window.ship}/dm-inbox/${patp2dec(ship)}`;
|
||||
return s.unreads[key] || emptyStats();
|
||||
},
|
||||
[ship]
|
||||
)
|
||||
|
@ -1,19 +1,18 @@
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import { useHistory, useParams } from "react-router-dom";
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import {
|
||||
Box,
|
||||
Col,
|
||||
Row,
|
||||
Text,
|
||||
Button,
|
||||
Action,
|
||||
LoadingSpinner,
|
||||
} from "@tlon/indigo-react";
|
||||
import * as Dialog from "@radix-ui/react-dialog";
|
||||
import { PropFunc } from "~/types";
|
||||
import { useRunIO } from "~/logic/lib/useRunIO";
|
||||
import useMetadataState from "~/logic/state/metadata";
|
||||
import { GroupSummary } from "~/views/landscape/components/GroupSummary";
|
||||
LoadingSpinner
|
||||
} from '@tlon/indigo-react';
|
||||
import * as Dialog from '@radix-ui/react-dialog';
|
||||
import { PropFunc } from '~/types';
|
||||
import { useRunIO } from '~/logic/lib/useRunIO';
|
||||
import useMetadataState from '~/logic/state/metadata';
|
||||
import { GroupSummary } from '~/views/landscape/components/GroupSummary';
|
||||
import {
|
||||
accept,
|
||||
decline,
|
||||
@ -22,13 +21,13 @@ import {
|
||||
join,
|
||||
Metadata,
|
||||
MetadataUpdatePreview,
|
||||
resourceFromPath,
|
||||
} from "@urbit/api";
|
||||
import useInviteState from "~/logic/state/invite";
|
||||
import useGroupState from "~/logic/state/group";
|
||||
import useGraphState from "~/logic/state/graph";
|
||||
import { useWaitForProps } from "~/logic/lib/useWaitForProps";
|
||||
import airlock from "~/logic/api";
|
||||
resourceFromPath
|
||||
} from '@urbit/api';
|
||||
import useInviteState from '~/logic/state/invite';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import useGraphState from '~/logic/state/graph';
|
||||
import { useWaitForProps } from '~/logic/lib/useWaitForProps';
|
||||
import airlock from '~/logic/api';
|
||||
|
||||
function InviteDialog({ children, ...rest }: PropFunc<typeof Col>) {
|
||||
return (
|
||||
@ -84,7 +83,7 @@ function inviteUrl(
|
||||
return `/~landscape${resource}`;
|
||||
}
|
||||
|
||||
if (metadata.config?.graph === "chat") {
|
||||
if (metadata.config?.graph === 'chat') {
|
||||
return `/~landscape/messages/resource/${metadata.config.graph}${resource}`;
|
||||
} else {
|
||||
return `/~landscape/home/resource/${metadata.config?.graph}${resource}`;
|
||||
@ -94,9 +93,9 @@ function inviteUrl(
|
||||
function useInviteAccept(resource: string, app?: string, uid?: string) {
|
||||
const { ship, name } = resourceFromPath(resource);
|
||||
const history = useHistory();
|
||||
const associations = useMetadataState((s) => s.associations);
|
||||
const groups = useGroupState((s) => s.groups);
|
||||
const graphKeys = useGraphState((s) => s.graphKeys);
|
||||
const associations = useMetadataState(s => s.associations);
|
||||
const groups = useGroupState(s => s.groups);
|
||||
const graphKeys = useGraphState(s => s.graphKeys);
|
||||
|
||||
const waiter = useWaitForProps({ associations, graphKeys, groups });
|
||||
return useRunIO<void, boolean>(
|
||||
@ -110,7 +109,6 @@ function useInviteAccept(resource: string, app?: string, uid?: string) {
|
||||
}
|
||||
|
||||
await airlock.poke(join(ship, name));
|
||||
await airlock.poke(accept(app, uid));
|
||||
await waiter((p) => {
|
||||
return (
|
||||
(resource in p.groups &&
|
||||
@ -119,10 +117,12 @@ function useInviteAccept(resource: string, app?: string, uid?: string) {
|
||||
resource in (p.associations?.groups ?? {})
|
||||
);
|
||||
});
|
||||
airlock.poke(accept(app, uid));
|
||||
return true;
|
||||
},
|
||||
(success: boolean) => {
|
||||
if (!success) {
|
||||
history.push('/');
|
||||
return;
|
||||
}
|
||||
const redir = inviteUrl(
|
||||
@ -147,11 +147,11 @@ export function Invite() {
|
||||
uid: string;
|
||||
}>();
|
||||
|
||||
const invite = useInviteState((s) => s.invites?.[app]?.[uid]);
|
||||
const invite = useInviteState(s => s.invites?.[app]?.[uid]);
|
||||
|
||||
return (
|
||||
<InviteDialog>
|
||||
{!!invite ? (
|
||||
{invite ? (
|
||||
<>
|
||||
{renderInviteContent(app, uid, invite)}
|
||||
<InviteActions app={app} uid={uid} invite={invite} />
|
||||
@ -166,7 +166,7 @@ export function Invite() {
|
||||
function InviteActions({
|
||||
app,
|
||||
uid,
|
||||
invite,
|
||||
invite
|
||||
}: {
|
||||
app: string;
|
||||
uid: string;
|
||||
@ -201,9 +201,9 @@ function InviteActions({
|
||||
|
||||
function GroupInvite({ uid, invite }: { uid: string; invite: IInvite }) {
|
||||
const {
|
||||
resource: { ship, name },
|
||||
resource: { ship, name }
|
||||
} = invite;
|
||||
const { associations, getPreview } = useMetadataState();
|
||||
const { getPreview } = useMetadataState();
|
||||
const [preview, setPreview] = useState<MetadataUpdatePreview | null>(null);
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
@ -218,8 +218,8 @@ function GroupInvite({ uid, invite }: { uid: string; invite: IInvite }) {
|
||||
return preview ? (
|
||||
<GroupSummary
|
||||
metadata={preview.metadata}
|
||||
channelCount={preview["channel-count"]}
|
||||
memberCount={preview["members"]}
|
||||
channelCount={preview['channel-count']}
|
||||
memberCount={preview['members']}
|
||||
/>
|
||||
) : (
|
||||
<LoadingSpinner />
|
||||
@ -232,9 +232,9 @@ function GraphInvite({ uid, invite }: { uid: string; invite: IInvite }) {
|
||||
|
||||
function renderInviteContent(app: string, uid: string, invite: IInvite) {
|
||||
switch (app) {
|
||||
case "groups":
|
||||
case 'groups':
|
||||
return <GroupInvite uid={uid} invite={invite} />;
|
||||
case "graph":
|
||||
case 'graph':
|
||||
return <GraphInvite uid={uid} invite={invite} />;
|
||||
default:
|
||||
return null;
|
||||
|
@ -8,13 +8,10 @@ import {
|
||||
Text
|
||||
} from '@tlon/indigo-react';
|
||||
import React, { useRef } from 'react';
|
||||
import { Link, useHistory } from 'react-router-dom';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Sigil } from '~/logic/lib/sigil';
|
||||
import { uxToHex } from '~/logic/lib/util';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useHarkState from '~/logic/state/hark';
|
||||
import useLaunchState from '~/logic/state/launch';
|
||||
import useInviteState from '~/logic/state/invite';
|
||||
import useLocalState, { selectLocalState } from '~/logic/state/local';
|
||||
import useSettingsState, { selectCalmState } from '~/logic/state/settings';
|
||||
import { Dropdown } from './Dropdown';
|
||||
@ -22,21 +19,13 @@ import { ProfileStatus } from './ProfileStatus';
|
||||
import ReconnectButton from './ReconnectButton';
|
||||
import { StatusBarItem } from './StatusBarItem';
|
||||
import { useTutorialModal } from './useTutorialModal';
|
||||
import {StatusBarJoins} from './StatusBarJoins';
|
||||
import { StatusBarJoins } from './StatusBarJoins';
|
||||
|
||||
const localSel = selectLocalState(['toggleOmnibox']);
|
||||
|
||||
const StatusBar = (props) => {
|
||||
const { ship } = props;
|
||||
const history = useHistory();
|
||||
const runtimeLag = useLaunchState(state => state.runtimeLag);
|
||||
const ourContact = useContactState(state => state.contacts[`~${ship}`]);
|
||||
const notificationsCount = useHarkState(state => state.notificationsCount);
|
||||
const doNotDisturb = useHarkState(state => state.doNotDisturb);
|
||||
const inviteState = useInviteState(state => state.invites);
|
||||
const invites = [].concat(
|
||||
...Object.values(inviteState).map(obj => Object.values(obj))
|
||||
);
|
||||
const metaKey = window.navigator.platform.includes('Mac') ? '⌘' : 'Ctrl+';
|
||||
const { toggleOmnibox } = useLocalState(localSel);
|
||||
const { hideAvatars } = useSettingsState(selectCalmState);
|
||||
@ -87,16 +76,6 @@ const StatusBar = (props) => {
|
||||
<Icon icon='Dashboard' color='black' />
|
||||
</Button>
|
||||
<StatusBarItem float={floatLeap} mr={2} onClick={() => toggleOmnibox()}>
|
||||
{!doNotDisturb && runtimeLag && (
|
||||
<Box display='block' right='-8px' top='-8px' position='absolute'>
|
||||
<Icon color='yellow' icon='Bullet' />
|
||||
</Box>
|
||||
)}
|
||||
{!doNotDisturb && (notificationsCount > 0 || invites.length > 0) && (
|
||||
<Box display='block' right='-8px' top='-8px' position='absolute'>
|
||||
<Icon color='blue' icon='Bullet' />
|
||||
</Box>
|
||||
)}
|
||||
<Icon icon='LeapArrow' />
|
||||
<Text ref={anchorRef} ml={2} color='black'>
|
||||
Leap
|
||||
|
@ -119,7 +119,7 @@ export function Omnibox(props: OmniboxProps): ReactElement {
|
||||
if (category === 'other') {
|
||||
return [
|
||||
'other',
|
||||
index.get('other').filter(({ app }) => app !== 'tutorial')
|
||||
index.get('other').filter(({ app }) => app !== 'tutorial' && app !== 'inbox')
|
||||
];
|
||||
}
|
||||
return [category, []];
|
||||
|
@ -7,8 +7,6 @@ import { cite, uxToHex } from '~/logic/lib/util';
|
||||
import { IconRef } from '~/types/util';
|
||||
import withState from '~/logic/lib/withState';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useHarkState from '~/logic/state/hark';
|
||||
import useLaunchState from '~/logic/state/launch';
|
||||
import useInviteState from '~/logic/state/invite';
|
||||
|
||||
function OmniboxResultChord(props: {
|
||||
@ -34,8 +32,6 @@ interface OmniboxResultProps {
|
||||
invites: Invites;
|
||||
link: string;
|
||||
navigate: () => void;
|
||||
notificationsCount: number;
|
||||
runtimeLag: any;
|
||||
selected: string;
|
||||
setSelection: () => void;
|
||||
subtext: string;
|
||||
@ -80,21 +76,11 @@ export class OmniboxResult extends Component<OmniboxResultProps, OmniboxResultSt
|
||||
icon: string,
|
||||
selected: string,
|
||||
link: string,
|
||||
invites: Invites,
|
||||
lag: any,
|
||||
notificationsCount: number,
|
||||
text: string,
|
||||
color: string
|
||||
): (any) {
|
||||
const iconFill =
|
||||
(this.state.hovered || selected === link) ? 'white' : 'black';
|
||||
const bulletFill =
|
||||
(this.state.hovered || selected === link) ? 'white' : 'blue';
|
||||
const lagFill =
|
||||
this.state.hovered || selected === link ? 'white' : 'yellow';
|
||||
const inviteCount = [].concat(
|
||||
...Object.values(invites).map(obj => Object.values(obj))
|
||||
);
|
||||
|
||||
let graphic: ReactElement = <div />;
|
||||
if (
|
||||
@ -120,35 +106,6 @@ export class OmniboxResult extends Component<OmniboxResultProps, OmniboxResultSt
|
||||
color={iconFill}
|
||||
/>
|
||||
);
|
||||
} else if (icon === 'inbox') {
|
||||
graphic = (
|
||||
<Box display='flex' verticalAlign='middle' position='relative'>
|
||||
<Icon
|
||||
display='inline-block'
|
||||
verticalAlign='middle'
|
||||
icon='Notifications'
|
||||
mr={2}
|
||||
size='18px'
|
||||
color={iconFill}
|
||||
/>
|
||||
{lag && (
|
||||
<Icon
|
||||
display='inline-block'
|
||||
icon='Bullet'
|
||||
style={{ position: 'absolute', top: -5, left: 5 }}
|
||||
color={lagFill}
|
||||
/>
|
||||
)}
|
||||
{(notificationsCount > 0 || inviteCount.length > 0) && (
|
||||
<Icon
|
||||
display='inline-block'
|
||||
icon='Bullet'
|
||||
style={{ position: 'absolute', top: -5, left: 5 }}
|
||||
color={bulletFill}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
} else if (icon === 'logout') {
|
||||
graphic = (
|
||||
<Icon
|
||||
@ -245,9 +202,6 @@ export class OmniboxResult extends Component<OmniboxResultProps, OmniboxResultSt
|
||||
cursor,
|
||||
navigate,
|
||||
selected,
|
||||
invites,
|
||||
notificationsCount,
|
||||
runtimeLag,
|
||||
contacts,
|
||||
setSelection,
|
||||
shiftDescription,
|
||||
@ -262,9 +216,6 @@ export class OmniboxResult extends Component<OmniboxResultProps, OmniboxResultSt
|
||||
icon,
|
||||
selected,
|
||||
link,
|
||||
invites,
|
||||
runtimeLag,
|
||||
notificationsCount,
|
||||
text,
|
||||
color
|
||||
);
|
||||
@ -334,8 +285,6 @@ export class OmniboxResult extends Component<OmniboxResultProps, OmniboxResultSt
|
||||
}
|
||||
|
||||
export default withState(OmniboxResult, [
|
||||
[useLaunchState, ['runtimeLag']],
|
||||
[useInviteState],
|
||||
[useHarkState, ['notificationsCount']],
|
||||
[useContactState]
|
||||
]);
|
||||
|
@ -108,7 +108,7 @@ export const Content = (props) => {
|
||||
if(Object.keys(associations).length > 0 && query.has('grid-note')) {
|
||||
history.push(getNotificationRedirect(query.get('grid-note')));
|
||||
}
|
||||
}, [location.search]);
|
||||
}, [location.search, associations]);
|
||||
|
||||
useShortcut('navForward', useCallback((e) => {
|
||||
e.preventDefault();
|
||||
|
@ -128,7 +128,8 @@ export const SidebarDmItem = React.memo((props: {
|
||||
!hideNicknames && contact?.nickname
|
||||
? contact?.nickname
|
||||
: cite(ship) ?? ship;
|
||||
const { unreads } = useHarkDm(ship) || { unreads: 0 };
|
||||
const { count, each } = useHarkDm(ship);
|
||||
const unreads = count + each.length;
|
||||
const img =
|
||||
contact?.avatar && !hideAvatars ? (
|
||||
<BaseImage
|
||||
|
Loading…
Reference in New Issue
Block a user