@@ -3,26 +3,39 @@ import type { GroupChannel } from '@sendbird/chat/groupChannel';
33import type { SendbirdError } from '@sendbird/chat' ;
44import { useSyncExternalStore } from 'use-sync-external-store/shim' ;
55
6+ import type {
7+ FileMessage ,
8+ FileMessageCreateParams ,
9+ MultipleFilesMessage ,
10+ MultipleFilesMessageCreateParams ,
11+ UserMessage ,
12+ UserMessageCreateParams ,
13+ UserMessageUpdateParams ,
14+ } from '@sendbird/chat/message' ;
15+
616import { SendableMessageType } from '../../../../utils' ;
717import { getMessageTopOffset } from '../utils' ;
818import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext' ;
919import { GroupChannelContext } from '../GroupChannelProvider' ;
10- import type { GroupChannelState } from '../types' ;
20+ import type { GroupChannelState , MessageActions } from '../types' ;
21+ import { useMessageActions } from './useMessageActions' ;
1122
12- export interface GroupChannelActions {
23+ export interface GroupChannelActions extends MessageActions {
1324 // Channel actions
1425 setCurrentChannel : ( channel : GroupChannel ) => void ;
1526 handleChannelError : ( error : SendbirdError ) => void ;
1627
28+ // Message actions
29+ sendUserMessage : ( params : UserMessageCreateParams ) => Promise < UserMessage > ;
30+ sendFileMessage : ( params : FileMessageCreateParams ) => Promise < FileMessage > ;
31+ sendMultipleFilesMessage : ( params : MultipleFilesMessageCreateParams ) => Promise < MultipleFilesMessage > ;
32+ updateUserMessage : ( messageId : number , params : UserMessageUpdateParams ) => Promise < UserMessage > ;
33+
1734 // UI actions
1835 setQuoteMessage : ( message : SendableMessageType | null ) => void ;
1936 setAnimatedMessageId : ( messageId : number | null ) => void ;
2037 setIsScrollBottomReached : ( isReached : boolean ) => void ;
2138
22- // Message actions
23- updateMessage : ( message : SendableMessageType , updatedMessage : SendableMessageType ) => Promise < void > ;
24- deleteMessage : ( message : SendableMessageType ) => Promise < void > ;
25-
2639 // Scroll actions
2740 scrollToBottom : ( animated ?: boolean ) => Promise < void > ;
2841 scrollToMessage : (
@@ -44,6 +57,41 @@ export const useGroupChannel = () => {
4457 const { markAsReadScheduler } = config ;
4558 const state : GroupChannelState = useSyncExternalStore ( store . subscribe , store . getState ) ;
4659
60+ const flagActions = {
61+ setAnimatedMessageId : ( messageId : number | null ) => {
62+ store . setState ( state => ( { ...state , animatedMessageId : messageId } ) ) ;
63+ } ,
64+
65+ setIsScrollBottomReached : ( isReached : boolean ) => {
66+ store . setState ( state => ( { ...state , isScrollBottomReached : isReached } ) ) ;
67+ } ,
68+ } ;
69+
70+ const scrollToBottom = async ( animated ?: boolean ) => {
71+ if ( ! state . scrollRef . current ) return ;
72+
73+ flagActions . setAnimatedMessageId ( null ) ;
74+ flagActions . setIsScrollBottomReached ( true ) ;
75+
76+ if ( config . isOnline && state . hasNext ( ) ) {
77+ await state . resetWithStartingPoint ( Number . MAX_SAFE_INTEGER ) ;
78+ state . scrollPubSub . publish ( 'scrollToBottom' , { animated } ) ;
79+ } else {
80+ state . scrollPubSub . publish ( 'scrollToBottom' , { animated } ) ;
81+ }
82+
83+ if ( state . currentChannel && ! state . hasNext ( ) ) {
84+ state . resetNewMessages ( ) ;
85+ if ( ! state . disableMarkAsRead ) {
86+ markAsReadScheduler . push ( state . currentChannel ) ;
87+ }
88+ }
89+ } ;
90+ const messageActions = useMessageActions ( {
91+ ...state ,
92+ scrollToBottom,
93+ } ) ;
94+
4795 const actions : GroupChannelActions = useMemo ( ( ) => ( {
4896 setCurrentChannel : ( channel : GroupChannel ) => {
4997 store . setState ( state => ( {
@@ -68,54 +116,11 @@ export const useGroupChannel = () => {
68116 } ) ) ;
69117 } ,
70118
71- updateMessage : async ( message : SendableMessageType , updatedMessage : SendableMessageType ) => {
72- store . setState ( state => ( {
73- ...state ,
74- messages : state . messages . map ( msg => msg . messageId === message . messageId ? updatedMessage : msg ,
75- ) ,
76- } ) ) ;
77- } ,
78-
79- deleteMessage : async ( message : SendableMessageType ) => {
80- store . setState ( state => ( {
81- ...state ,
82- messages : state . messages . filter ( msg => msg . messageId !== message . messageId ) ,
83- } ) ) ;
84- } ,
85-
86119 setQuoteMessage : ( message : SendableMessageType | null ) => {
87120 store . setState ( state => ( { ...state , quoteMessage : message } ) ) ;
88121 } ,
89122
90- setAnimatedMessageId : ( messageId : number | null ) => {
91- store . setState ( state => ( { ...state , animatedMessageId : messageId } ) ) ;
92- } ,
93-
94- setIsScrollBottomReached : ( isReached : boolean ) => {
95- store . setState ( state => ( { ...state , isScrollBottomReached : isReached } ) ) ;
96- } ,
97-
98- scrollToBottom : async ( animated ?: boolean ) => {
99- if ( ! state . scrollRef . current ) return ;
100-
101- actions . setAnimatedMessageId ( null ) ;
102- actions . setIsScrollBottomReached ( true ) ;
103-
104- if ( config . isOnline && state . hasNext ( ) ) {
105- await state . resetWithStartingPoint ( Number . MAX_SAFE_INTEGER ) ;
106- state . scrollPubSub . publish ( 'scrollToBottom' , { animated } ) ;
107- } else {
108- state . scrollPubSub . publish ( 'scrollToBottom' , { animated } ) ;
109- }
110-
111- if ( state . currentChannel && ! state . hasNext ( ) ) {
112- state . resetNewMessages ( ) ;
113- if ( ! state . disableMarkAsRead ) {
114- markAsReadScheduler . push ( state . currentChannel ) ;
115- }
116- }
117- } ,
118-
123+ scrollToBottom,
119124 scrollToMessage : async (
120125 createdAt : number ,
121126 messageId : number ,
@@ -139,15 +144,15 @@ export const useGroupChannel = () => {
139144
140145 clickHandler . deactivate ( ) ;
141146
142- actions . setAnimatedMessageId ( null ) ;
147+ flagActions . setAnimatedMessageId ( null ) ;
143148 const message = state . messages . find (
144149 ( it ) => it . messageId === messageId || it . createdAt === createdAt ,
145150 ) ;
146151
147152 if ( message ) {
148153 const topOffset = getMessageTopOffset ( message . createdAt ) ;
149154 if ( topOffset ) state . scrollPubSub . publish ( 'scroll' , { top : topOffset , animated : scrollAnimated } ) ;
150- if ( messageFocusAnimated ?? true ) actions . setAnimatedMessageId ( messageId ) ;
155+ if ( messageFocusAnimated ?? true ) flagActions . setAnimatedMessageId ( messageId ) ;
151156 } else {
152157 await state . resetWithStartingPoint ( createdAt ) ;
153158 setTimeout ( ( ) => {
@@ -159,7 +164,7 @@ export const useGroupChannel = () => {
159164 animated : scrollAnimated ,
160165 } ) ;
161166 }
162- if ( messageFocusAnimated ?? true ) actions . setAnimatedMessageId ( messageId ) ;
167+ if ( messageFocusAnimated ?? true ) flagActions . setAnimatedMessageId ( messageId ) ;
163168 } ) ;
164169 }
165170
@@ -181,6 +186,8 @@ export const useGroupChannel = () => {
181186 } ) ;
182187 }
183188 } ,
189+ ...flagActions ,
190+ ...messageActions ,
184191 } ) , [ store , state , config . isOnline , markAsReadScheduler ] ) ;
185192
186193 return { state, actions } ;
0 commit comments