From 1f849528b2de6ad170d2feff6048d42947403ed3 Mon Sep 17 00:00:00 2001 From: ~latter-bolden Date: Fri, 1 Dec 2023 15:56:27 -0500 Subject: [PATCH 1/5] dms: remove negotiation check when initiating multi dms --- ui/src/dms/NewDm.tsx | 46 ++++++++++-------------------- ui/src/logic/useMessageSelector.ts | 9 ------ 2 files changed, 15 insertions(+), 40 deletions(-) diff --git a/ui/src/dms/NewDm.tsx b/ui/src/dms/NewDm.tsx index 29425d692c..c83a60a2d6 100644 --- a/ui/src/dms/NewDm.tsx +++ b/ui/src/dms/NewDm.tsx @@ -12,14 +12,7 @@ import { dmListPath } from '@/logic/utils'; import MessageSelector from './MessageSelector'; export default function NewDM() { - const { - sendDm, - validShips, - whom, - isMultiDm, - confirmedMultiDmMismatch, - existingMultiDm, - } = useMessageSelector(); + const { sendDm, validShips, whom } = useMessageSelector(); const dropZoneId = 'chat-new-dm-input-dropzone'; const { isDragging, isOver } = useDragAndDrop(dropZoneId); const isMobile = useIsMobile(); @@ -27,8 +20,6 @@ export default function NewDM() { const isScrolling = useIsScrolling(scrollElementRef); const { isChatInputFocused } = useChatInputFocus(); const shouldApplyPaddingBottom = isMobile && !isChatInputFocused; - const shouldBlockInput = - isMultiDm && !existingMultiDm && confirmedMultiDmMismatch; return ( } footer={ - shouldBlockInput ? ( -
- Your version of the app does not match some of the members of this - chat. -
- ) : ( -
- -
- ) +
+ +
} > diff --git a/ui/src/logic/useMessageSelector.ts b/ui/src/logic/useMessageSelector.ts index 3e0a5f596d..40580eb0ff 100644 --- a/ui/src/logic/useMessageSelector.ts +++ b/ui/src/logic/useMessageSelector.ts @@ -11,7 +11,6 @@ import { useMultiDms, useSendMessage, } from '@/state/chat'; -import { useNegotiateMulti } from '@/state/negotiation'; import { createStorageKey, newUv } from './utils'; export default function useMessageSelector() { @@ -28,13 +27,6 @@ export default function useMessageSelector() { const { data: unreads } = useDmUnreads(); const { mutate: sendMessage } = useSendMessage(); const { mutateAsync: createMultiDm } = useCreateMultiDm(); - const { match: negotiationMatch, isLoading: negotiationLoading } = - useNegotiateMulti( - ships.map((option) => option.value), - 'chat', - 'chat' - ); - const confirmedMultiDmMismatch = !negotiationLoading && !negotiationMatch; const existingDm = useMemo(() => { if (ships.length !== 1) { @@ -169,7 +161,6 @@ export default function useMessageSelector() { return { isMultiDm, - confirmedMultiDmMismatch, action, existingDm, existingMultiDm, From cc657861c077752534929ea7624ea1d63484395c Mon Sep 17 00:00:00 2001 From: fang Date: Fri, 1 Dec 2023 23:17:00 +0100 Subject: [PATCH 2/5] chat: support on-demand negotiation without poking So that we can find out their version before even sending a club invite. --- desk/app/chat.hoon | 3 +++ desk/mar/chat/negotiate.hoon | 12 ++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 desk/mar/chat/negotiate.hoon diff --git a/desk/app/chat.hoon b/desk/app/chat.hoon index bf0e81c3ef..fb0467ccd2 100644 --- a/desk/app/chat.hoon +++ b/desk/app/chat.hoon @@ -427,6 +427,9 @@ |= [=mark =vase] |^ ^+ cor ?+ mark ~|(bad-poke/mark !!) + %chat-negotiate + ::TODO arguably should just be a /mar/negotiate + (emit (initiate:neg !<(@p vase) dap.bowl)) :: %chat-dm-rsvp =+ !<(=rsvp:dm:c vase) diff --git a/desk/mar/chat/negotiate.hoon b/desk/mar/chat/negotiate.hoon new file mode 100644 index 0000000000..10e02f62df --- /dev/null +++ b/desk/mar/chat/negotiate.hoon @@ -0,0 +1,12 @@ +|_ who=@p +++ grad %ship +++ grow + |% + ++ noun who + -- +++ grab + |% + ++ noun @p + ++ json (su:dejs:format ;~(pfix sig fed:ag)) + -- +-- From 5187a11afe64fd39adb81fb1c9a0b66461c62ba6 Mon Sep 17 00:00:00 2001 From: ~latter-bolden Date: Sat, 2 Dec 2023 14:46:25 -0500 Subject: [PATCH 3/5] dms: make sure we have all version negotiations when setting up a new multidm and update the ui to show when were still checking --- ui/src/dms/NewDm.tsx | 59 ++++++++++++++++++++++-------- ui/src/logic/useMessageSelector.ts | 15 ++++++++ ui/src/state/negotiation.ts | 49 ++++++++++++++++++++++--- 3 files changed, 101 insertions(+), 22 deletions(-) diff --git a/ui/src/dms/NewDm.tsx b/ui/src/dms/NewDm.tsx index c83a60a2d6..caf3fda759 100644 --- a/ui/src/dms/NewDm.tsx +++ b/ui/src/dms/NewDm.tsx @@ -1,4 +1,4 @@ -import React, { useRef } from 'react'; +import React, { useMemo, useRef } from 'react'; import cn from 'classnames'; import ChatInput from '@/chat/ChatInput/ChatInput'; import Layout from '@/components/Layout/Layout'; @@ -9,10 +9,19 @@ import { useIsScrolling } from '@/logic/scroll'; import { useIsMobile } from '@/logic/useMedia'; import { useChatInputFocus } from '@/logic/ChatInputFocusContext'; import { dmListPath } from '@/logic/utils'; +import LoadingSpinner from '@/components/LoadingSpinner/LoadingSpinner'; import MessageSelector from './MessageSelector'; export default function NewDM() { - const { sendDm, validShips, whom } = useMessageSelector(); + const { + sendDm, + validShips, + whom, + isMultiDm, + existingMultiDm, + multiDmVersionMismatch, + haveAllNegotiations, + } = useMessageSelector(); const dropZoneId = 'chat-new-dm-input-dropzone'; const { isDragging, isOver } = useDragAndDrop(dropZoneId); const isMobile = useIsMobile(); @@ -20,6 +29,8 @@ export default function NewDM() { const isScrolling = useIsScrolling(scrollElementRef); const { isChatInputFocused } = useChatInputFocus(); const shouldApplyPaddingBottom = isMobile && !isChatInputFocused; + const shouldBlockInput = + isMultiDm && !existingMultiDm && multiDmVersionMismatch; return ( } footer={ -
- -
+ shouldBlockInput ? ( +
+ {haveAllNegotiations ? ( + 'Your version of the app does not match some of the members of this chat.' + ) : ( + <> + {' '} + {' '} + + Checking version compatibility + {' '} + + )} +
+ ) : ( +
+ +
+ ) } > diff --git a/ui/src/logic/useMessageSelector.ts b/ui/src/logic/useMessageSelector.ts index 40580eb0ff..811751c01e 100644 --- a/ui/src/logic/useMessageSelector.ts +++ b/ui/src/logic/useMessageSelector.ts @@ -11,6 +11,7 @@ import { useMultiDms, useSendMessage, } from '@/state/chat'; +import { useInitShipNegotiation, useNegotiateMulti } from '@/state/negotiation'; import { createStorageKey, newUv } from './utils'; export default function useMessageSelector() { @@ -28,6 +29,18 @@ export default function useMessageSelector() { const { mutate: sendMessage } = useSendMessage(); const { mutateAsync: createMultiDm } = useCreateMultiDm(); + useInitShipNegotiation(shipValues, 'chat'); + const { + match: negotiationMatch, + isLoading: negotiationLoading, + haveAllNegotiations, + } = useNegotiateMulti( + ships.map((option) => option.value), + 'chat', + 'chat' + ); + const multiDmVersionMismatch = !negotiationLoading && !negotiationMatch; + const existingDm = useMemo(() => { if (ships.length !== 1) { return null; @@ -161,6 +174,8 @@ export default function useMessageSelector() { return { isMultiDm, + multiDmVersionMismatch, + haveAllNegotiations, action, existingDm, existingMultiDm, diff --git a/ui/src/state/negotiation.ts b/ui/src/state/negotiation.ts index 022b89fb21..8dedd24e91 100644 --- a/ui/src/state/negotiation.ts +++ b/ui/src/state/negotiation.ts @@ -1,4 +1,4 @@ -import { useEffect, useMemo, useRef } from 'react'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { debounce } from 'lodash'; import api from '@/api'; @@ -99,13 +99,50 @@ export function useNegotiateMulti(ships: string[], app: string, agent: string) { const { data, ...rest } = useNegotiation(app, agent); if (rest.isLoading || rest.isError || data === undefined) { - return { ...rest, match: false }; + return { ...rest, match: false, haveAllNegotiations: false }; } - const allShipsMatch = ships + const shipKeys = ships .filter((ship) => ship !== window.our) - .map((ship) => `${ship}/${agent}`) - .every((ship) => ship in data && data[ship] === 'match'); + .map((ship) => `${ship}/${agent}`); - return { ...rest, match: allShipsMatch }; + const allShipsMatch = shipKeys.every( + (ship) => ship in data && data[ship] === 'match' + ); + + const haveAllNegotiations = shipKeys.every((ship) => ship in data); + + return { ...rest, match: allShipsMatch, haveAllNegotiations }; +} + +// If we haven't already interacted with a ship, but need to know its +// negotiation status, we have to inititate negotiation manually +export function useInitShipNegotiation(ships: string[], app: string) { + const { data } = useNegotiation(app, app); + const unknownShips = useMemo( + () => ships.filter((ship) => `${ship}/${app}` in (data || {}) === false), + [ships, app, data] + ); + const negotiateUnknownShips = useCallback( + async (shipsToCheck: string[]) => { + const responses: Promise[] = []; + shipsToCheck.forEach((ship) => { + responses.push( + api.poke({ + app, + mark: 'chat-negotiate', + json: ship, + }) + ); + }); + await Promise.all(responses); + }, + [app] + ); + + useEffect(() => { + if (unknownShips.length > 0) { + negotiateUnknownShips(unknownShips); + } + }, [unknownShips, negotiateUnknownShips]); } From 5f9dd69a1e2540765375c28f4f35aee92c1c211b Mon Sep 17 00:00:00 2001 From: ~latter-bolden Date: Sat, 2 Dec 2023 15:04:05 -0500 Subject: [PATCH 4/5] dms: remove weird space escaping from newdm --- ui/src/dms/NewDm.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ui/src/dms/NewDm.tsx b/ui/src/dms/NewDm.tsx index caf3fda759..1aabe32008 100644 --- a/ui/src/dms/NewDm.tsx +++ b/ui/src/dms/NewDm.tsx @@ -48,11 +48,8 @@ export default function NewDM() { 'Your version of the app does not match some of the members of this chat.' ) : ( <> - {' '} - {' '} - - Checking version compatibility - {' '} + + Checking version compatibility )} From 76d646c0056257335e52589f9cbe8542599bca8f Mon Sep 17 00:00:00 2001 From: ~latter-bolden Date: Sat, 2 Dec 2023 15:38:14 -0500 Subject: [PATCH 5/5] dms: force negotiation whenver status isnt match, not just if we dont have any status --- ui/src/logic/useMessageSelector.ts | 7 +++++-- ui/src/state/negotiation.ts | 12 ++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/ui/src/logic/useMessageSelector.ts b/ui/src/logic/useMessageSelector.ts index 811751c01e..966b340e2b 100644 --- a/ui/src/logic/useMessageSelector.ts +++ b/ui/src/logic/useMessageSelector.ts @@ -11,7 +11,10 @@ import { useMultiDms, useSendMessage, } from '@/state/chat'; -import { useInitShipNegotiation, useNegotiateMulti } from '@/state/negotiation'; +import { + useForceNegotiationUpdate, + useNegotiateMulti, +} from '@/state/negotiation'; import { createStorageKey, newUv } from './utils'; export default function useMessageSelector() { @@ -29,7 +32,7 @@ export default function useMessageSelector() { const { mutate: sendMessage } = useSendMessage(); const { mutateAsync: createMultiDm } = useCreateMultiDm(); - useInitShipNegotiation(shipValues, 'chat'); + useForceNegotiationUpdate(shipValues, 'chat'); const { match: negotiationMatch, isLoading: negotiationLoading, diff --git a/ui/src/state/negotiation.ts b/ui/src/state/negotiation.ts index 8dedd24e91..e80cd70b49 100644 --- a/ui/src/state/negotiation.ts +++ b/ui/src/state/negotiation.ts @@ -115,12 +115,16 @@ export function useNegotiateMulti(ships: string[], app: string, agent: string) { return { ...rest, match: allShipsMatch, haveAllNegotiations }; } -// If we haven't already interacted with a ship, but need to know its -// negotiation status, we have to inititate negotiation manually -export function useInitShipNegotiation(ships: string[], app: string) { +export function useForceNegotiationUpdate(ships: string[], app: string) { const { data } = useNegotiation(app, app); const unknownShips = useMemo( - () => ships.filter((ship) => `${ship}/${app}` in (data || {}) === false), + () => + ships.filter( + (ship) => + !data || + !(`${ship}/${app}` in data) || + data[`${ship}/${app}`] !== 'match' + ), [ships, app, data] ); const negotiateUnknownShips = useCallback(