Bluesky app fork with some witchin' additions 💫 witchsky.app
bluesky fork client
117
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add ability to edit group clip clop name (#10275)

authored by

DS Boyce and committed by
GitHub
adca192f 59150430

+160 -13
+18 -8
src/screens/Messages/ConversationSettings.tsx
··· 20 20 import {ConvoProvider, useConvo} from '#/state/messages/convo' 21 21 import {ConvoStatus} from '#/state/messages/convo/types' 22 22 import {useModerationOpts} from '#/state/preferences/moderation-opts' 23 + import {useEditGroupName} from '#/state/queries/messages/edit-group-name' 23 24 import {useGetConvoAvailabilityQuery} from '#/state/queries/messages/get-convo-availability' 24 25 import {useGetConvoForMembers} from '#/state/queries/messages/get-convo-for-members' 25 26 import {useLeaveConvo} from '#/state/queries/messages/leave-conversation' ··· 717 718 const convoState = useConvo() 718 719 const {currentAccount} = useSession() 719 720 721 + const groupName = convoState.getGroupInfo?.()?.name ?? '' 722 + const [newGroupName, setNewGroupName] = useState(groupName) 723 + 724 + const [isLocked, setIsLocked] = useState(false) 725 + 720 726 const isOwner = 721 727 currentAccount?.did == null 722 728 ? false 723 729 : convoState.getPrimaryMember?.()?.did === currentAccount.did 724 730 731 + const {mutate: editGroupName} = useEditGroupName(convo.id, { 732 + onError: e => { 733 + setNewGroupName(groupName) 734 + logger.error('Failed to edit group chat name', {message: e}) 735 + Toast.show(l`Failed to edit group chat name`, { 736 + type: 'error', 737 + }) 738 + }, 739 + }) 740 + 725 741 const {mutate: muteConvo} = useMuteConvo(convo.id, { 726 742 onSuccess: data => { 727 743 if (data.convo.muted) { ··· 755 771 const lockChatPrompt = Prompt.usePromptControl() 756 772 const leaveChatPrompt = Prompt.usePromptControl() 757 773 758 - const [groupName, setGroupName] = useState( 759 - convoState.getGroupInfo?.()?.name ?? '', 760 - ) 761 - const [newGroupName, setNewGroupName] = useState(groupName) 762 - 763 - const [isLocked, setIsLocked] = useState(false) 764 - 765 774 const handleToggleMute = () => { 766 775 muteConvo({mute: !convo?.muted}) 767 776 } ··· 777 786 } 778 787 779 788 const handleEditName = () => { 780 - setGroupName(newGroupName) 789 + editGroupName({name: newGroupName}) 781 790 editNamePrompt.close() 782 791 } 783 792 ··· 1045 1054 autoCapitalize="none" 1046 1055 autoComplete="off" 1047 1056 autoCorrect={false} 1057 + autoFocus 1048 1058 onSubmitEditing={onConfirm} 1049 1059 /> 1050 1060 </TextField.Root>
+24 -4
src/state/messages/convo/agent.ts
··· 116 116 this.isGroup = this.isGroup.bind(this) 117 117 this.getGroupInfo = this.getGroupInfo.bind(this) 118 118 this.getPrimaryMember = this.getPrimaryMember.bind(this) 119 + this.updateGroupName = this.updateGroupName.bind(this) 119 120 } 120 121 121 122 private commit() { ··· 655 656 656 657 const nextCursor = this.oldestRev // for TS 657 658 const response = await networkRetry(2, () => { 658 - return this.agent.api.chat.bsky.convo.getMessages( 659 + return this.agent.chat.bsky.convo.getMessages( 659 660 { 660 661 cursor: nextCursor, 661 662 convoId: this.convoId, ··· 889 890 this.commit() 890 891 } 891 892 893 + updateGroupName(name: string) { 894 + if ( 895 + this.convo && 896 + bsky.dangerousIsType<ChatBskyConvoDefs.GroupConvo>( 897 + this.convo.kind, 898 + ChatBskyConvoDefs.isGroupConvo, 899 + ) 900 + ) { 901 + this.convo = { 902 + ...this.convo, 903 + kind: { 904 + ...this.convo.kind, 905 + name, 906 + }, 907 + } 908 + } 909 + this.commit() 910 + } 911 + 892 912 async processPendingMessages() { 893 913 logger.debug( 894 914 `processing messages (${this.pendingMessages.size} remaining)`, ··· 1388 1408 1389 1409 getPrimaryMember(): ChatBskyActorDefs.ProfileViewBasic | undefined { 1390 1410 if (this.isGroup()) { 1391 - return this.recipients?.find(r => { 1411 + return this.convo?.members.find(m => { 1392 1412 if ( 1393 1413 bsky.dangerousIsType<ChatBskyActorDefs.GroupConvoMember>( 1394 - r.kind, 1414 + m.kind, 1395 1415 ChatBskyActorDefs.isGroupConvoMember, 1396 1416 ) 1397 1417 ) { 1398 - return r.kind.role === 'owner' 1418 + return m.kind.role === 'owner' 1399 1419 } else { 1400 1420 throw new Error( 1401 1421 'Expected a GroupConvoMember, got an unknown kind of member',
+10 -1
src/state/messages/convo/index.tsx
··· 6 6 useState, 7 7 useSyncExternalStore, 8 8 } from 'react' 9 - import {type ChatBskyConvoDefs} from '@atproto/api' 9 + import {ChatBskyConvoDefs} from '@atproto/api' 10 10 import {useFocusEffect} from '@react-navigation/native' 11 11 import {useQueryClient} from '@tanstack/react-query' 12 12 ··· 129 129 | undefined 130 130 if (data && convo.convo && data.muted !== convo.convo.muted) { 131 131 convo.updateMuted(data.muted) 132 + } 133 + if ( 134 + data && 135 + convo.convo && 136 + ChatBskyConvoDefs.isGroupConvo(data.kind) && 137 + ChatBskyConvoDefs.isGroupConvo(convo.convo.kind) && 138 + data.kind.name !== convo.convo.kind.name 139 + ) { 140 + convo.updateGroupName(data.kind.name) 132 141 } 133 142 } 134 143 })
+108
src/state/queries/messages/edit-group-name.ts
··· 1 + import { 2 + ChatBskyConvoDefs, 3 + type ChatBskyConvoListConvos, 4 + type ChatBskyGroupEditGroup, 5 + } from '@atproto/api' 6 + import { 7 + type InfiniteData, 8 + useMutation, 9 + useQueryClient, 10 + } from '@tanstack/react-query' 11 + 12 + import {DM_SERVICE_HEADERS} from '#/lib/constants' 13 + import {logger} from '#/logger' 14 + import {useAgent} from '#/state/session' 15 + import {RQKEY as CONVO_KEY} from './conversation' 16 + import {RQKEY_ROOT as CONVO_LIST_KEY} from './list-conversations' 17 + 18 + export function useEditGroupName( 19 + convoId: string | undefined, 20 + { 21 + onSuccess, 22 + onError, 23 + }: { 24 + onSuccess?: (data: ChatBskyGroupEditGroup.OutputSchema) => void 25 + onError?: (error: Error) => void 26 + }, 27 + ) { 28 + const queryClient = useQueryClient() 29 + const agent = useAgent() 30 + 31 + return useMutation({ 32 + mutationFn: async ({name: groupName}: {name: string}) => { 33 + if (!convoId) throw new Error('No convoId provided') 34 + const {data} = await agent.chat.bsky.group.editGroup( 35 + {convoId, name: groupName}, 36 + {headers: DM_SERVICE_HEADERS, encoding: 'application/json'}, 37 + ) 38 + return data 39 + }, 40 + onMutate: ({name: groupName}) => { 41 + if (!convoId) return 42 + 43 + const prevConvo = queryClient.getQueryData<ChatBskyConvoDefs.ConvoView>( 44 + CONVO_KEY(convoId), 45 + ) 46 + const prevListEntries = queryClient.getQueriesData< 47 + InfiniteData<ChatBskyConvoListConvos.OutputSchema> 48 + >({queryKey: [CONVO_LIST_KEY]}) 49 + 50 + // Update for a single chat thread 51 + queryClient.setQueryData<ChatBskyConvoDefs.ConvoView>( 52 + CONVO_KEY(convoId), 53 + prev => { 54 + if (!prev) return 55 + if (!ChatBskyConvoDefs.isGroupConvo(prev.kind)) return prev 56 + return { 57 + ...prev, 58 + kind: { 59 + ...prev.kind, 60 + name: groupName, 61 + }, 62 + } 63 + }, 64 + ) 65 + 66 + // Update for the chat list 67 + queryClient.setQueriesData< 68 + InfiniteData<ChatBskyConvoListConvos.OutputSchema> 69 + >({queryKey: [CONVO_LIST_KEY]}, prev => { 70 + if (!prev?.pages) return 71 + return { 72 + ...prev, 73 + pages: prev.pages.map(page => ({ 74 + ...page, 75 + convos: page.convos.map(convo => { 76 + if (convo.id !== convoId) return convo 77 + if (!ChatBskyConvoDefs.isGroupConvo(convo.kind)) return convo 78 + return { 79 + ...convo, 80 + kind: { 81 + ...convo.kind, 82 + name: groupName, 83 + }, 84 + } 85 + }), 86 + })), 87 + } 88 + }) 89 + 90 + return {prevConvo, prevListEntries} 91 + }, 92 + onSuccess: data => { 93 + onSuccess?.(data) 94 + }, 95 + onError: (e, _variables, context) => { 96 + logger.error(e) 97 + if (context?.prevConvo && convoId) { 98 + queryClient.setQueryData(CONVO_KEY(convoId), context.prevConvo) 99 + } 100 + if (context?.prevListEntries) { 101 + for (const [key, data] of context.prevListEntries) { 102 + queryClient.setQueryData(key, data) 103 + } 104 + } 105 + onError?.(e) 106 + }, 107 + }) 108 + }