Skip to content

Commit

Permalink
dms: react-queryify message sending
Browse files Browse the repository at this point in the history
  • Loading branch information
latter-bolden committed Nov 9, 2023
1 parent c431dd9 commit f23df2a
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 74 deletions.
5 changes: 3 additions & 2 deletions ui/src/chat/ChatInput/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import React, {
import { useSearchParams } from 'react-router-dom';
import * as Popover from '@radix-ui/react-popover';
import {
SendMessageVariables,
useIsShipBlocked,
useShipHasBlockedUs,
useUnblockShipMutation,
Expand Down Expand Up @@ -57,7 +58,7 @@ import {
ReplyTuple,
} from '@/types/channel';
import { CacheId } from '@/state/channel/channel';
import { WritTuple } from '@/types/dms';
import { WritDelta, WritTuple } from '@/types/dms';
import messageSender from '@/logic/messageSender';
import { useChatInputFocus } from '@/logic/ChatInputFocusContext';

Expand All @@ -68,7 +69,7 @@ interface ChatInputProps {
showReply?: boolean;
className?: string;
sendDisabled?: boolean;
sendDm?: (whom: string, essay: PostEssay, replying?: string) => void;
sendDm?: (variables: SendMessageVariables) => void;
sendChatMessage?: ({
cacheId,
essay,
Expand Down
5 changes: 3 additions & 2 deletions ui/src/dms/DMThread.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Link } from 'react-router-dom';
import { VirtuosoHandle } from 'react-virtuoso';
import { useEventListener } from 'usehooks-ts';
import bigInt from 'big-integer';
import { useChatState, useWrit } from '@/state/chat';
import { useChatState, useWrit, useSendMessage } from '@/state/chat';
import ChatInput from '@/chat/ChatInput/ChatInput';
import BranchIcon from '@/components/icons/BranchIcon';
import X16Icon from '@/components/icons/X16Icon';
Expand Down Expand Up @@ -43,7 +43,8 @@ export default function DMThread() {
if (!writ) return '0';
return writ.seal.time;
}, [writ]);
const { sendMessage } = useChatState.getState();
// const { sendMessage } = useChatState.getState();
const { mutate: sendMessage } = useSendMessage();
const { isOpen: leapIsOpen } = useLeap();
const dropZoneId = `chat-thread-input-dropzone-${id}`;
const { isDragging, isOver } = useDragAndDrop(dropZoneId);
Expand Down
3 changes: 2 additions & 1 deletion ui/src/dms/Dm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { useIsScrolling } from '@/logic/scroll';
import { useChatInputFocus } from '@/logic/ChatInputFocusContext';
import { dmListPath, isGroups } from '@/logic/utils';
import useNegotiation from '@/state/negotiation';
import { sendMessage } from '@/state/chat';
import { useSendMessage } from '@/state/chat';
import MessageSelector from './MessageSelector';
import DmSearch from './DmSearch';

Expand Down Expand Up @@ -110,6 +110,7 @@ export default function Dm() {
const dropZoneId = `chat-dm-input-dropzone-${ship}`;
const { isDragging, isOver } = useDragAndDrop(dropZoneId);
// const { sendMessage } = useChatState.getState();
const { mutate: sendMessage } = useSendMessage();
const contact = useContact(ship);
const { data } = useConnectivityCheck(ship || '');
const navigate = useNavigate();
Expand Down
10 changes: 8 additions & 2 deletions ui/src/dms/MultiDm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import {
import { Link } from 'react-router-dom';
import ChatInput from '@/chat/ChatInput/ChatInput';
import Layout from '@/components/Layout/Layout';
import { useChatState, useMultiDm, useMultiDmIsPending } from '@/state/chat';
import {
useChatState,
useMultiDm,
useMultiDmIsPending,
useSendMessage,
} from '@/state/chat';
import { useIsMobile } from '@/logic/useMedia';
import { dmListPath, isGroups, pluralize } from '@/logic/utils';
import useMessageSelector from '@/logic/useMessageSelector';
Expand Down Expand Up @@ -90,6 +95,7 @@ export default function MultiDm() {
const shouldApplyPaddingBottom = isGroups && isMobile && !isChatInputFocused;
const dmParticipants = [...(club?.team ?? []), ...(club?.hive ?? [])];
const negotiationMatch = useNegotiateMulti(dmParticipants, 'chat', 'chat');
const { mutate: sendMessage } = useSendMessage();

const {
isSelectingMessage,
Expand All @@ -105,7 +111,7 @@ export default function MultiDm() {
}
}, [clubId, club]);

const { sendMessage } = useChatState.getState();
// const { sendMessage } = useChatState.getState();

const handleLeave = useCallback(() => {
navigate(dmListPath);
Expand Down
24 changes: 13 additions & 11 deletions ui/src/logic/messageSender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import {
PostEssay,
Story,
} from '@/types/channel';
import { JSONToInlines } from './tiptap';
import { createMessage } from '@/state/chat/utils';
import { WritDelta } from '@/types/dms';
import { SendMessageVariables } from '@/state/chat';
import { isImageUrl } from './utils';
import { JSONToInlines } from './tiptap';

interface MessageSender {
whom: string;
Expand All @@ -19,7 +22,7 @@ interface MessageSender {
blocks: Block[];
text: string;
now: number;
sendDm?: (whom: string, essay: PostEssay, replying?: string) => void;
sendDm?: (variables: SendMessageVariables) => void;
sendChatMessage?: ({
cacheId,
essay,
Expand Down Expand Up @@ -107,16 +110,14 @@ export default function messageSender({
},
},
];
const message = createMessage(whom, { ...essay, content }, replying);

if (sendDm) {
sendDm(
sendDm({
whom,
{
...essay,
content,
},
replying
);
message,
replying,
});
} else if (sendChatMessage) {
sendChatMessage({
cacheId,
Expand All @@ -135,7 +136,7 @@ export default function messageSender({

img.onerror = () => {
if (sendDm) {
sendDm(whom, essay, replying);
sendDm({ whom, message, replying });
} else if (sendChatMessage) {
sendChatMessage({
cacheId,
Expand All @@ -151,7 +152,8 @@ export default function messageSender({
};
};
} else if (sendDm) {
sendDm(whom, essay, replying);
const message = createMessage(whom, essay, replying);
sendDm({ whom, message, replying });
} else if (sendChatMessage) {
sendChatMessage({
cacheId,
Expand Down
18 changes: 15 additions & 3 deletions ui/src/logic/useMessageSelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@ import { useCallback, useEffect, useMemo } from 'react';
import { useLocation, useNavigate } from 'react-router';
import { useLocalStorage } from 'usehooks-ts';
import { ShipOption } from '@/components/ShipSelector';
import { useChatState, useDmUnreads, useMultiDms } from '@/state/chat';
import {
SendMessageVariables,
useChatState,
useDmUnreads,
useMultiDms,
useSendMessage,
} from '@/state/chat';
import createClub from '@/state/chat/createClub';
import { PostEssay } from '@/types/channel';
import { createMessage } from '@/state/chat/utils';
import { WritDelta } from '@/types/dms';
import { createStorageKey, newUv } from './utils';

export default function useMessageSelector() {
Expand All @@ -21,6 +29,7 @@ export default function useMessageSelector() {
const shipValues = useMemo(() => ships.map((o) => o.value), [ships]);
const multiDms = useMultiDms();
const { data: unreads } = useDmUnreads();
const { mutate: sendMessage } = useSendMessage();

const existingDm = useMemo(() => {
if (ships.length !== 1) {
Expand Down Expand Up @@ -86,12 +95,15 @@ export default function useMessageSelector() {
);

const sendDm = useCallback(
async (whom: string, essay: PostEssay) => {
async (variables: SendMessageVariables) => {
const { whom } = variables;
if (isMultiDm && shipValues && whom !== existingMultiDm) {
await createClub(whom, shipValues);
}

useChatState.getState().sendMessage(whom, essay);
// useChatState.getState().sendMessage(whom, essay);
sendMessage(variables);

setShips([]);
navigate(`/dm/${isMultiDm ? whom : whom}`);
},
Expand Down
90 changes: 38 additions & 52 deletions ui/src/state/chat/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1036,65 +1036,51 @@ export async function optimisticDMAction(
await api.poke<ClubAction | DmAction>(action);
}

export async function sendMessage(
whom: string,
mem: PostEssay,
replying: string | undefined
) {
const isDM = whomIsDm(whom);
const { id, time } = makeId();
const memo: Omit<PostEssay, 'kind-data'> = {
content: mem.content,
author: mem.author,
sent: time,
export interface SendMessageVariables {
whom: string;
message: {
id: string;
delta: WritDelta;
};
replying?: string;
}

let diff: WritDelta;
if (!replying) {
diff = {
add: {
memo,
kind: null,
time: null,
},
};
} else {
diff = {
reply: {
id,
meta: null,
delta: {
add: {
memo,
time: null,
},
},
},
};
}

if (replying) {
await optimisticDMAction(whom, replying, diff);
} else {
await optimisticDMAction(whom, id, diff);
}
export function useSendMessage() {
const mutationFn = async ({
whom,
message,
replying,
}: SendMessageVariables) => {
const { action } = getActionAndEvent(
whom,
replying || message.id,
message.delta
);
await api.poke<ClubAction | DmAction>(action);
};

// TODO: tracking message for sending/sent status
return useMutation({
mutationFn,
onMutate: (variables) => {
const { whom, message, replying } = variables;
const queryKey = ['dms', whom, 'infinite'];
infiniteDMsUpdater(queryKey, {
id: replying || message.id,
delta: message.delta,
});
},
onSettled: (_data, _error, variables) => {
const { whom } = variables;
const queryKey = ['dms', whom, 'infinite'];
queryClient.invalidateQueries(queryKey);
},
});

// return useMutation(async () => {
// if (replying) {
// await optimisticDMAction(whom, replying, diff);
// } else {
// await optimisticDMAction(whom, id, diff);
// }
// });
// TODO: tracking message for sending/sent arrows
}

export async function delDm(whom: string, id: string) {
// const dif = { del: null };
// if (whomIsDm(whom)) {
// } else {
// }
//
}

export function useAddDmReactMutation() {
Expand Down
51 changes: 50 additions & 1 deletion ui/src/state/chat/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Club } from '@/types/dms';
import { PostEssay } from '@/types/channel';
import { Club, WritDelta } from '@/types/dms';
import { formatUd, unixToDa } from '@urbit/aura';

export default function emptyMultiDm(): Club {
return {
Expand All @@ -12,3 +14,50 @@ export default function emptyMultiDm(): Club {
},
};
}

function makeId() {
const time = Date.now();
return {
id: `${window.our}/${formatUd(unixToDa(time))}`,
time,
};
}

export function createMessage(
whom: string,
mem: PostEssay,
replying?: string
): { id: string; delta: WritDelta } {
const { id, time } = makeId();
const memo: Omit<PostEssay, 'kind-data'> = {
content: mem.content,
author: mem.author,
sent: time,
};

let delta: WritDelta;
if (!replying) {
delta = {
add: {
memo,
kind: null,
time: null,
},
};
} else {
delta = {
reply: {
id,
meta: null,
delta: {
add: {
memo,
time: null,
},
},
},
};
}

return { id, delta };
}

0 comments on commit f23df2a

Please sign in to comment.