-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(uikit): added group channel operators fragment
- Loading branch information
Showing
18 changed files
with
366 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
...t-react-native/src/domain/groupChannelOperators/component/GroupChannelOperatorsHeader.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import React, { useContext } from 'react'; | ||
|
||
import { Icon, useHeaderStyle } from '@sendbird/uikit-react-native-foundation'; | ||
|
||
import { GroupChannelOperatorsContexts } from '../module/moduleContext'; | ||
import type { GroupChannelOperatorsProps } from '../types'; | ||
|
||
const GroupChannelOperatorsHeader = ({ | ||
onPressHeaderLeft, | ||
onPressHeaderRight, | ||
}: GroupChannelOperatorsProps['Header']) => { | ||
const { headerTitle } = useContext(GroupChannelOperatorsContexts.Fragment); | ||
const { HeaderComponent } = useHeaderStyle(); | ||
return ( | ||
<HeaderComponent | ||
title={headerTitle} | ||
left={<Icon icon={'arrow-left'} />} | ||
onPressLeft={onPressHeaderLeft} | ||
right={<Icon icon={'plus'} />} | ||
onPressRight={onPressHeaderRight} | ||
/> | ||
); | ||
}; | ||
|
||
export default GroupChannelOperatorsHeader; |
28 changes: 28 additions & 0 deletions
28
...kit-react-native/src/domain/groupChannelOperators/component/GroupChannelOperatorsList.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import React from 'react'; | ||
import { FlatList, ListRenderItem } from 'react-native'; | ||
import { useSafeAreaInsets } from 'react-native-safe-area-context'; | ||
|
||
import type { SendbirdMember } from '@sendbird/uikit-utils'; | ||
import { useFreshCallback } from '@sendbird/uikit-utils'; | ||
|
||
import type { GroupChannelOperatorsProps } from '../types'; | ||
|
||
const GroupChannelOperatorsList = ({ | ||
operators, | ||
renderUser, | ||
ListEmptyComponent, | ||
}: GroupChannelOperatorsProps['List']) => { | ||
const renderItem: ListRenderItem<SendbirdMember> = useFreshCallback(({ item }) => renderUser?.({ user: item })); | ||
const { left, right } = useSafeAreaInsets(); | ||
|
||
return ( | ||
<FlatList | ||
data={operators} | ||
renderItem={renderItem} | ||
contentContainerStyle={{ paddingLeft: left, paddingRight: right, flexGrow: 1 }} | ||
ListEmptyComponent={ListEmptyComponent} | ||
/> | ||
); | ||
}; | ||
|
||
export default GroupChannelOperatorsList; |
18 changes: 18 additions & 0 deletions
18
...ct-native/src/domain/groupChannelOperators/component/GroupChannelOperatorsStatusEmpty.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React from 'react'; | ||
import { StyleSheet, View } from 'react-native'; | ||
|
||
import TypedPlaceholder from '../../../components/TypedPlaceholder'; | ||
|
||
const GroupChannelOperatorsStatusEmpty = () => { | ||
return ( | ||
<View style={styles.container}> | ||
<TypedPlaceholder type={'no-users'} /> | ||
</View> | ||
); | ||
}; | ||
|
||
const styles = StyleSheet.create({ | ||
container: { flex: 1, justifyContent: 'center', alignItems: 'center' }, | ||
}); | ||
|
||
export default GroupChannelOperatorsStatusEmpty; |
18 changes: 18 additions & 0 deletions
18
...-native/src/domain/groupChannelOperators/component/GroupChannelOperatorsStatusLoading.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React from 'react'; | ||
import { StyleSheet, View } from 'react-native'; | ||
|
||
import TypedPlaceholder from '../../../components/TypedPlaceholder'; | ||
|
||
const GroupChannelOperatorsStatusLoading = () => { | ||
return ( | ||
<View style={styles.container}> | ||
<TypedPlaceholder type={'loading'} /> | ||
</View> | ||
); | ||
}; | ||
|
||
const styles = StyleSheet.create({ | ||
container: { flex: 1, justifyContent: 'center', alignItems: 'center' }, | ||
}); | ||
|
||
export default GroupChannelOperatorsStatusLoading; |
6 changes: 6 additions & 0 deletions
6
packages/uikit-react-native/src/domain/groupChannelOperators/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export { default as GroupChannelOperatorsList } from './component/GroupChannelOperatorsList'; | ||
export { default as GroupChannelOperatorsHeader } from './component/GroupChannelOperatorsHeader'; | ||
export { default as GroupChannelOperatorsStatusLoading } from './component/GroupChannelOperatorsStatusLoading'; | ||
export { default as GroupChannelOperatorsStatusEmpty } from './component/GroupChannelOperatorsStatusEmpty'; | ||
export { default as createGroupChannelOperatorsModule } from './module/createGroupChannelOperatorsModule'; | ||
export { GroupChannelOperatorsContextsProvider, GroupChannelOperatorsContexts } from './module/moduleContext'; |
19 changes: 19 additions & 0 deletions
19
...eact-native/src/domain/groupChannelOperators/module/createGroupChannelOperatorsModule.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import GroupChannelOperatorsHeader from '../component/GroupChannelOperatorsHeader'; | ||
import GroupChannelOperatorsList from '../component/GroupChannelOperatorsList'; | ||
import GroupChannelOperatorsStatusEmpty from '../component/GroupChannelOperatorsStatusEmpty'; | ||
import GroupChannelOperatorsStatusLoading from '../component/GroupChannelOperatorsStatusLoading'; | ||
import type { GroupChannelOperatorsModule } from '../types'; | ||
import { GroupChannelOperatorsContextsProvider } from './moduleContext'; | ||
|
||
const createGroupChannelOperatorsModule = ({ | ||
Header = GroupChannelOperatorsHeader, | ||
List = GroupChannelOperatorsList, | ||
StatusLoading = GroupChannelOperatorsStatusLoading, | ||
StatusEmpty = GroupChannelOperatorsStatusEmpty, | ||
Provider = GroupChannelOperatorsContextsProvider, | ||
...module | ||
}: Partial<GroupChannelOperatorsModule> = {}): GroupChannelOperatorsModule => { | ||
return { Header, List, Provider, StatusEmpty, StatusLoading, ...module }; | ||
}; | ||
|
||
export default createGroupChannelOperatorsModule; |
24 changes: 24 additions & 0 deletions
24
packages/uikit-react-native/src/domain/groupChannelOperators/module/moduleContext.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import React, { createContext } from 'react'; | ||
|
||
import ProviderLayout from '../../../components/ProviderLayout'; | ||
import { useLocalization } from '../../../hooks/useContext'; | ||
import type { GroupChannelOperatorsContextsType, GroupChannelOperatorsModule } from '../types'; | ||
|
||
export const GroupChannelOperatorsContexts: GroupChannelOperatorsContextsType = { | ||
Fragment: createContext({ | ||
headerTitle: '', | ||
}), | ||
}; | ||
|
||
export const GroupChannelOperatorsContextsProvider: GroupChannelOperatorsModule['Provider'] = ({ children }) => { | ||
const { STRINGS } = useLocalization(); | ||
return ( | ||
<ProviderLayout> | ||
<GroupChannelOperatorsContexts.Fragment.Provider | ||
value={{ headerTitle: STRINGS.GROUP_CHANNEL_OPERATORS.HEADER_TITLE }} | ||
> | ||
{children} | ||
</GroupChannelOperatorsContexts.Fragment.Provider> | ||
</ProviderLayout> | ||
); | ||
}; |
43 changes: 43 additions & 0 deletions
43
packages/uikit-react-native/src/domain/groupChannelOperators/types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import type React from 'react'; | ||
|
||
import type { SendbirdGroupChannel, SendbirdMember } from '@sendbird/uikit-utils'; | ||
|
||
import type { CommonComponent } from '../../types'; | ||
|
||
export type GroupChannelOperatorsProps = { | ||
Fragment: { | ||
channel: SendbirdGroupChannel; | ||
onPressHeaderLeft: GroupChannelOperatorsProps['Header']['onPressHeaderLeft']; | ||
onPressHeaderRight: GroupChannelOperatorsProps['Header']['onPressHeaderRight']; | ||
renderUser?: GroupChannelOperatorsProps['List']['renderUser']; | ||
}; | ||
Header: { | ||
onPressHeaderLeft: () => void; | ||
onPressHeaderRight: () => void; | ||
}; | ||
List: { | ||
renderUser: (props: { user: SendbirdMember }) => React.ReactElement | null; | ||
operators: SendbirdMember[]; | ||
ListEmptyComponent?: React.ReactElement; | ||
}; | ||
}; | ||
|
||
/** | ||
* Internal context for GroupChannelOperators | ||
* For example, the developer can create a custom header | ||
* with getting data from the domain context | ||
* */ | ||
export type GroupChannelOperatorsContextsType = { | ||
Fragment: React.Context<{ | ||
headerTitle: string; | ||
}>; | ||
}; | ||
export interface GroupChannelOperatorsModule { | ||
Provider: CommonComponent; | ||
Header: CommonComponent<GroupChannelOperatorsProps['Header']>; | ||
List: CommonComponent<GroupChannelOperatorsProps['List']>; | ||
StatusEmpty: CommonComponent; | ||
StatusLoading: CommonComponent; | ||
} | ||
|
||
export type GroupChannelOperatorsFragment = CommonComponent<GroupChannelOperatorsProps['Fragment']>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
packages/uikit-react-native/src/fragments/createGroupChannelOperatorsFragment.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import React from 'react'; | ||
|
||
import { useChannelHandler } from '@sendbird/uikit-chat-hooks'; | ||
import { useActionMenu } from '@sendbird/uikit-react-native-foundation'; | ||
import { ifOperator, useForceUpdate, useFreshCallback, useUniqId } from '@sendbird/uikit-utils'; | ||
|
||
import UserActionBar from '../components/UserActionBar'; | ||
import { createGroupChannelOperatorsModule } from '../domain/groupChannelOperators'; | ||
import type { GroupChannelOperatorsFragment, GroupChannelOperatorsModule } from '../domain/groupChannelOperators/types'; | ||
import { useLocalization, useProfileCard, useSendbirdChat } from '../hooks/useContext'; | ||
|
||
const name = 'createGroupChannelOperatorsFragment'; | ||
const createGroupChannelOperatorsFragment = ( | ||
initModule?: Partial<GroupChannelOperatorsModule>, | ||
): GroupChannelOperatorsFragment => { | ||
const GroupChannelOperatorsModule = createGroupChannelOperatorsModule(initModule); | ||
|
||
return ({ channel, onPressHeaderLeft, onPressHeaderRight, renderUser }) => { | ||
const uniqId = useUniqId(name); | ||
const forceUpdate = useForceUpdate(); | ||
|
||
const { STRINGS } = useLocalization(); | ||
const { sdk, currentUser } = useSendbirdChat(); | ||
const { openMenu } = useActionMenu(); | ||
const { show } = useProfileCard(); | ||
|
||
useChannelHandler(sdk, `${name}_${uniqId}`, { | ||
onUserLeft(channel) { | ||
if (channel.url === channel.url) forceUpdate(); | ||
}, | ||
onUserBanned(channel) { | ||
if (channel.url === channel.url) forceUpdate(); | ||
}, | ||
onOperatorUpdated(channel) { | ||
if (channel.url === channel.url) forceUpdate(); | ||
}, | ||
}); | ||
|
||
const _renderUser: NonNullable<typeof renderUser> = useFreshCallback((props) => { | ||
if (renderUser) return renderUser(props); | ||
|
||
const { user } = props; | ||
return ( | ||
<UserActionBar | ||
muted={false} | ||
uri={user.profileUrl} | ||
label={user.role === 'operator' ? STRINGS.LABELS.USER_BAR_OPERATOR : ''} | ||
name={ | ||
(user.nickname || STRINGS.LABELS.USER_NO_NAME) + | ||
(user.userId === currentUser?.userId ? STRINGS.LABELS.USER_BAR_ME_POSTFIX : '') | ||
} | ||
disabled={user.userId === currentUser?.userId} | ||
onPressActionMenu={ifOperator(channel.myRole, () => { | ||
openMenu({ | ||
title: user.nickname || STRINGS.LABELS.USER_NO_NAME, | ||
menuItems: [ | ||
{ | ||
title: ifOperator(user.role, STRINGS.LABELS.UNREGISTER_OPERATOR, STRINGS.LABELS.REGISTER_AS_OPERATOR), | ||
onPress: ifOperator( | ||
user.role, | ||
() => channel.removeOperators([user.userId]), | ||
() => channel.addOperators([user.userId]), | ||
), | ||
}, | ||
], | ||
}); | ||
})} | ||
onPressAvatar={() => show(user)} | ||
/> | ||
); | ||
}); | ||
|
||
return ( | ||
<GroupChannelOperatorsModule.Provider> | ||
<GroupChannelOperatorsModule.Header | ||
onPressHeaderLeft={onPressHeaderLeft} | ||
onPressHeaderRight={async () => onPressHeaderRight()} | ||
/> | ||
|
||
<GroupChannelOperatorsModule.List | ||
operators={channel.members.filter((it) => it.role === 'operator')} | ||
renderUser={_renderUser} | ||
ListEmptyComponent={<GroupChannelOperatorsModule.StatusEmpty />} | ||
/> | ||
</GroupChannelOperatorsModule.Provider> | ||
); | ||
}; | ||
}; | ||
|
||
export default createGroupChannelOperatorsFragment; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.