From 1af02cb38acd94997c16a1cf9994bc6446433849 Mon Sep 17 00:00:00 2001 From: Patrick O'Sullivan Date: Thu, 2 Nov 2023 11:43:02 -0500 Subject: [PATCH 1/5] mobile: hide nav on gallery item and diary note comment input focus --- ui/src/diary/DiaryCommentField.tsx | 26 ++++++ ui/src/diary/DiaryNote.tsx | 8 ++ ui/src/heap/HeapDetail.tsx | 5 +- ui/src/heap/HeapTextInput.tsx | 132 +++++++++++++++++------------ 4 files changed, 114 insertions(+), 57 deletions(-) diff --git a/ui/src/diary/DiaryCommentField.tsx b/ui/src/diary/DiaryCommentField.tsx index fee3f8779d..2f0ea3a79a 100644 --- a/ui/src/diary/DiaryCommentField.tsx +++ b/ui/src/diary/DiaryCommentField.tsx @@ -17,6 +17,7 @@ import useGroupPrivacy from '@/logic/useGroupPrivacy'; import { captureGroupsAnalyticsEvent } from '@/logic/analytics'; import { useChannelCompatibility } from '@/logic/channel'; import Tooltip from '@/components/Tooltip'; +import { useChatInputFocus } from '@/logic/ChatInputFocusContext'; interface DiaryCommentFieldProps { flag: string; @@ -44,6 +45,7 @@ export default function DiaryCommentField({ const { mutateAsync: addQuip } = useAddQuipMutation(); const { privacy } = useGroupPrivacy(groupFlag); const { compatible, text } = useChannelCompatibility(`diary/${chFlag}`); + const { handleFocus, handleBlur, isChatInputFocused } = useChatInputFocus(); /** * This handles submission for new Curios; for edits, see EditCurioForm @@ -152,6 +154,30 @@ export default function DiaryCommentField({ quipReply, ]); + useEffect(() => { + if (messageEditor && !messageEditor.isDestroyed) { + if (!isChatInputFocused && messageEditor.isFocused) { + handleFocus(); + } + + if (isChatInputFocused && !messageEditor.isFocused) { + handleBlur(); + } + } + + return () => { + if (isChatInputFocused) { + handleBlur(); + } + }; + }, [ + isChatInputFocused, + messageEditor, + messageEditor?.isFocused, + handleFocus, + handleBlur, + ]); + const onClick = useCallback( () => messageEditor && onSubmit(messageEditor), [messageEditor, onSubmit] diff --git a/ui/src/diary/DiaryNote.tsx b/ui/src/diary/DiaryNote.tsx index d39c0eadbe..1d70ba2e64 100644 --- a/ui/src/diary/DiaryNote.tsx +++ b/ui/src/diary/DiaryNote.tsx @@ -38,6 +38,8 @@ import { useChannelCompatibility, useChannelIsJoined } from '@/logic/channel'; import { useGroupsAnalyticsEvent } from '@/logic/useAnalyticsEvent'; import { ViewProps } from '@/types/groups'; import { useConnectivityCheck } from '@/state/vitals'; +import { useIsMobile } from '@/logic/useMedia'; +import { useChatInputFocus } from '@/logic/ChatInputFocusContext'; import DiaryComment, { DiaryCommentProps } from './DiaryComment'; import DiaryCommentField from './DiaryCommentField'; import DiaryContent from './DiaryContent/DiaryContent'; @@ -117,6 +119,9 @@ export default function DiaryNote({ title }: ViewProps) { const brief = useDiaryBrief(chFlag); const sort = useDiaryCommentSortMode(chFlag); const perms = useDiaryPerms(chFlag); + const isMobile = useIsMobile(); + const { isChatInputFocused } = useChatInputFocus(); + const shouldApplyPaddingBottom = isMobile && !isChatInputFocused; const { compatible } = useChannelCompatibility(nest); const { mutateAsync: joinDiary } = useJoinDiaryMutation(); const joinChannel = useCallback(async () => { @@ -180,6 +185,9 @@ export default function DiaryNote({ title }: ViewProps) { if (!note.essay || status === 'loading') { return ( { + if (messageEditor && !messageEditor.isDestroyed) { + if (!isChatInputFocused && messageEditor.isFocused && comment) { + handleFocus(); + } + + if (isChatInputFocused && !messageEditor.isFocused && comment) { + handleBlur(); + } + } + + return () => { + if (isChatInputFocused) { + handleBlur(); + } + }; + }, [ + comment, + isChatInputFocused, + messageEditor, + messageEditor?.isFocused, + handleFocus, + handleBlur, + ]); + const onClick = useCallback( () => messageEditor && onSubmit(messageEditor), [messageEditor, onSubmit] @@ -209,67 +235,61 @@ export default function HeapTextInput({ // TODO: Set a sane length limit for comments return ( - <> +
messageEditor.commands.focus()} + > + {chatInfo.blocks.length > 0 ? ( +
+ Attached: + {chatInfo.blocks.length} reference + {chatInfo.blocks.length === 1 ? '' : 's'} + +
+ ) : null}
messageEditor.commands.focus()} + className={cn( + 'w-full', + comment ? 'flex flex-row items-end' : 'relative flex h-full' + )} > - {chatInfo.blocks.length > 0 ? ( -
- Attached: - {chatInfo.blocks.length} reference - {chatInfo.blocks.length === 1 ? '' : 's'} + tag, only style + // the fake placeholder when the field is empty + messageEditor.getText() === '' ? 'text-gray-400' : '' + )} + /> + {!sendDisabled ? ( + -
+ ) : null} -
- tag, only style - // the fake placeholder when the field is empty - messageEditor.getText() === '' ? 'text-gray-400' : '' - )} - /> - {!sendDisabled ? ( - - - - ) : null} -
- {isMobile && messageEditor.isFocused ? ( - - ) : null} - +
); } From 29c831594b709b3bc9ae3d611b348bb9093cdb11 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 3 Nov 2023 13:31:51 +0000 Subject: [PATCH 2/5] update glob: [skip actions] --- desk/desk.docket-0 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desk/desk.docket-0 b/desk/desk.docket-0 index 4fe8fc7f5f..13c3dec808 100644 --- a/desk/desk.docket-0 +++ b/desk/desk.docket-0 @@ -2,7 +2,7 @@ info+'Start, host, and cultivate communities. Own your communications, organize your resources, and share documents. Groups is a decentralized platform that integrates with Talk, Notebook, and Gallery for a full, communal suite of tools.' color+0xef.f0f4 image+'https://bootstrap.urbit.org/icon-groups.svg?v=1' - glob-http+['https://bootstrap.urbit.org/glob-0vpkb66.7906k.fhl40.sfbag.3h35r.glob' 0vpkb66.7906k.fhl40.sfbag.3h35r] + glob-http+['https://bootstrap.urbit.org/glob-0v6.b9t70.6dgc8.ecj0v.q9i0r.dcvfv.glob' 0v6.b9t70.6dgc8.ecj0v.q9i0r.dcvfv] base+'groups' version+[4 8 1] website+'https://tlon.io' From 05e50318dacc5b34098a0c126901559f31336d18 Mon Sep 17 00:00:00 2001 From: Patrick O'Sullivan Date: Fri, 3 Nov 2023 08:59:59 -0500 Subject: [PATCH 3/5] images: catch more failed promises in image uploads --- ui/src/state/storage/upload.ts | 44 +++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/ui/src/state/storage/upload.ts b/ui/src/state/storage/upload.ts index ec31bd79e7..261bec2080 100644 --- a/ui/src/state/storage/upload.ts +++ b/ui/src/state/storage/upload.ts @@ -22,10 +22,12 @@ function prefixEndpoint(endpoint: string) { } function imageSize(url: string) { - const size = getImageSize(url).then<[number, number]>(({ width, height }) => [ - width, - height, - ]); + const size = getImageSize(url) + .then<[number, number]>(({ width, height }) => [width, height]) + .catch((e) => { + console.log('failed to get image size', { e }); + return undefined; + }); return size; } @@ -169,12 +171,17 @@ export const useFileStore = create((set, get) => ({ return ''; }); updateStatus(uploader, key, 'success'); - imageSize(fileUrl).then((s) => - updateFile(uploader, key, { - size: s, - url: fileUrl, - }) - ); + imageSize(fileUrl) + .then((s) => + updateFile(uploader, key, { + size: s, + url: fileUrl, + }) + ) + .catch((e) => { + console.log('failed to get image size', { e }); + return ''; + }); }) .catch((error: any) => { updateStatus( @@ -217,12 +224,17 @@ export const useFileStore = create((set, get) => ({ .then(() => { const fileUrl = url.split('?')[0]; updateStatus(uploader, key, 'success'); - imageSize(fileUrl).then((s) => - updateFile(uploader, key, { - size: s, - url: fileUrl, - }) - ); + imageSize(fileUrl) + .then((s) => + updateFile(uploader, key, { + size: s, + url: fileUrl, + }) + ) + .catch((e) => { + console.log('failed to get image size', { e }); + return ''; + }); }) .catch((error: any) => { updateStatus( From b31027d6b18571e752f5002138160e909c55dd71 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 3 Nov 2023 15:31:52 +0000 Subject: [PATCH 4/5] update glob: [skip actions] --- desk/desk.docket-0 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desk/desk.docket-0 b/desk/desk.docket-0 index 13c3dec808..c5da328d57 100644 --- a/desk/desk.docket-0 +++ b/desk/desk.docket-0 @@ -2,7 +2,7 @@ info+'Start, host, and cultivate communities. Own your communications, organize your resources, and share documents. Groups is a decentralized platform that integrates with Talk, Notebook, and Gallery for a full, communal suite of tools.' color+0xef.f0f4 image+'https://bootstrap.urbit.org/icon-groups.svg?v=1' - glob-http+['https://bootstrap.urbit.org/glob-0v6.b9t70.6dgc8.ecj0v.q9i0r.dcvfv.glob' 0v6.b9t70.6dgc8.ecj0v.q9i0r.dcvfv] + glob-http+['https://bootstrap.urbit.org/glob-0v4.ft52g.gnf1b.l0di5.04tuu.qm6j0.glob' 0v4.ft52g.gnf1b.l0di5.04tuu.qm6j0] base+'groups' version+[4 8 1] website+'https://tlon.io' From b2310ff32231bafcbd9117e9b36cb1500c043150 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 3 Nov 2023 15:31:52 +0000 Subject: [PATCH 5/5] update glob: [skip actions] --- talk/desk.docket-0 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/talk/desk.docket-0 b/talk/desk.docket-0 index 4ae8d399fc..e9c1c54c60 100644 --- a/talk/desk.docket-0 +++ b/talk/desk.docket-0 @@ -2,7 +2,7 @@ info+'Send encrypted direct messages to one or many friends. Talk is a simple chat tool for catching up, getting work done, and everything in between.' color+0x10.5ec7 image+'https://bootstrap.urbit.org/icon-talk.svg?v=1' - glob-http+['https://bootstrap.urbit.org/glob-0v7.lnq57.22fup.bdspn.9v0b5.gotem.glob' 0v7.lnq57.22fup.bdspn.9v0b5.gotem] + glob-http+['https://bootstrap.urbit.org/glob-0v2.nmce3.b4ei2.15157.h3bmf.dc5r4.glob' 0v2.nmce3.b4ei2.15157.h3bmf.dc5r4] base+'talk' version+[4 8 1] website+'https://tlon.io'