Skip to content

Instantly share code, notes, and snippets.

@bang9
Last active January 19, 2023 01:41
Show Gist options
  • Save bang9/58772ad1cf96151ba3a54cf91484dbdb to your computer and use it in GitHub Desktop.
Save bang9/58772ad1cf96151ba3a54cf91484dbdb to your computer and use it in GitHub Desktop.
Customization UIKit for ReactNative
import React, { useCallback, useEffect, useState } from 'react';
import { GroupChannelFilter } from '@sendbird/chat/groupChannel';
import { createGroupChannelListFragment, useSendbirdChat } from '@sendbird/uikit-react-native';
import { useAppNavigation } from '../../../hooks/useAppNavigation';
import { Routes } from '../../../libs/navigation';
const GroupChannelListFragment = createGroupChannelListFragment();
const GroupChannelListScreen = () => {
const { navigation } = useAppNavigation<Routes.GroupChannelList>();
const { sdk, currentUser } = useSendbirdChat();
// Create a collection creator
const collectionCreator = useCallback(() => {
const doctorId = 'doctor-id-1234';
const userId = currentUser!.userId;
const filter = new GroupChannelFilter();
filter.channelUrlsFilter = [`${userId}-${doctorId}`];
return sdk.groupChannel.createGroupChannelCollection({ filter });
}, [currentUser]);
return (
<GroupChannelListFragment
onPressCreateChannel={(channelType) => {
navigation.navigate(Routes.GroupChannelCreate, { channelType });
}}
onPressChannel={(channel) => {
navigation.navigate(Routes.GroupChannel, { channelUrl: channel.url });
}}
collectionCreator={collectionCreator}
/>
);
};
export default GroupChannelListScreen;
// Based on https://github.com/sendbird/sendbird-uikit-react-native/blob/main/sample/src/screens/uikit-app/GroupChannelScreen.tsx
import React, { useState } from 'react';
import { KeyboardAvoidingView, Platform, Pressable, TextInput, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { GroupChannelProps, createGroupChannelFragment, useSendbirdChat } from '@sendbird/uikit-react-native';
import { Icon } from '@sendbird/uikit-react-native-foundation';
import { useAppNavigation } from '../../hooks/useAppNavigation';
import { Routes } from '../../libs/navigation';
const CustomInput = ({ onSendUserMessage }: GroupChannelProps['Input']) => {
const { bottom } = useSafeAreaInsets();
const [text, setText] = useState('');
const onSend = () => {
if (text.length > 0) {
setText('');
onSendUserMessage(text);
}
};
return (
<KeyboardAvoidingView
behavior={Platform.select({ ios: 'padding' as const, default: undefined })}
keyboardVerticalOffset={-bottom}
>
<View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: bottom }}>
<TextInput value={text} onChangeText={setText} style={{ flex: 1, height: 50, backgroundColor: 'red' }} />
<Pressable onPress={onSend}>
<Icon icon={'streaming'} size={24} color={'red'} />
</Pressable>
</View>
</KeyboardAvoidingView>
);
};
const GroupChannelFragment = createGroupChannelFragment({
Input: CustomInput,
});
const GroupChannelScreen = () => {
const { navigation, params } = useAppNavigation<Routes.GroupChannel>();
const { sdk } = useSendbirdChat();
const [channel] = useState(() => sdk.GroupChannel.buildFromSerializedData(params.serializedChannel));
return (
<GroupChannelFragment
channel={channel}
onPressMediaMessage={(fileMessage, deleteMessage) => {
// Navigate to media viewer
navigation.navigate(Routes.FileViewer, {
serializedFileMessage: fileMessage.serialize(),
deleteMessage,
});
}}
onChannelDeleted={() => {
// Should leave channel, navigate to channel list
navigation.navigate(Routes.GroupChannelList);
}}
onPressHeaderLeft={() => {
// Navigate back
navigation.goBack();
}}
onPressHeaderRight={() => {
// Navigate to group channel settings
navigation.navigate(Routes.GroupChannelSettings, { serializedChannel: params.serializedChannel });
}}
/>
);
};
export default GroupChannelScreen;
// Based on https://github.com/sendbird/sendbird-uikit-react-native/blob/main/sample/src/App.tsx
import Notifee from '@notifee/react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { DarkTheme, DefaultTheme, NavigationContainer } from '@react-navigation/native';
import React, { useEffect } from 'react';
import { SendbirdUIKitContainer, useSendbirdChat } from '@sendbird/uikit-react-native';
import { DarkUIKitTheme, LightUIKitTheme, createTheme } from '@sendbird/uikit-react-native-foundation';
import { APP_ID } from './env';
import {
ClipboardService,
FileService,
GetTranslucent,
MediaService,
NotificationService,
RootStack,
SetSendbirdSDK,
} from './factory';
import useAppearance from './hooks/useAppearance';
import { Routes, navigationRef } from './libs/navigation';
import { onForegroundAndroid, onForegroundIOS } from './libs/notification';
import {
ErrorInfoScreen,
GroupChannelCreateScreen,
GroupChannelInviteScreen,
GroupChannelMembersScreen,
GroupChannelScreen,
GroupChannelSettingsScreen,
GroupChannelTabs,
HomeScreen,
PaletteScreen,
SignInScreen,
StorybookScreen,
ThemeColorsScreen,
} from './screens';
import FileViewerScreen from './screens/uikit-app/FileViewerScreen';
const MyUIKitTheme = createTheme({
colorScheme: 'light',
colors: (palette) => ({
...LightUIKitTheme.colors,
ui: {
...LightUIKitTheme.colors.ui,
message: {
incoming: {
enabled: {
background: palette.background200,
textMsg: palette.secondary200,
textEdited: palette.onBackgroundLight01,
textSenderName: palette.onBackgroundLight01,
textTime: palette.onBackgroundLight01,
},
pressed: {
background: palette.background500,
textMsg: palette.secondary400,
textEdited: palette.onBackgroundLight01,
textSenderName: palette.onBackgroundLight01,
textTime: palette.onBackgroundLight01,
},
},
outgoing: {
enabled: {
background: palette.primary100,
textMsg: palette.onBackgroundDark01,
textEdited: palette.onBackgroundLight01,
textSenderName: palette.onBackgroundLight01,
textTime: palette.onBackgroundLight01,
},
pressed: {
background: palette.primary300,
textMsg: palette.onBackgroundDark02,
textEdited: palette.onBackgroundLight01,
textSenderName: palette.onBackgroundLight01,
textTime: palette.onBackgroundLight01,
},
},
},
},
}),
});
const App = () => {
const { scheme } = useAppearance();
const isLightTheme = scheme === 'light';
return (
<SendbirdUIKitContainer
appId={APP_ID}
chatOptions={{
localCacheStorage: AsyncStorage,
onInitialized: SetSendbirdSDK,
enableAutoPushTokenRegistration: true,
enableChannelListTypingIndicator: true,
enableChannelListMessageReceiptStatus: true,
}}
platformServices={{
file: FileService,
notification: NotificationService,
clipboard: ClipboardService,
media: MediaService,
}}
styles={{
defaultHeaderTitleAlign: 'left', //'center',
theme: isLightTheme ? MyUIKitTheme : DarkUIKitTheme,
statusBarTranslucent: GetTranslucent(),
}}
errorBoundary={{ ErrorInfoComponent: ErrorInfoScreen }}
>
<Navigations />
</SendbirdUIKitContainer>
);
};
const Navigations = () => {
const { currentUser } = useSendbirdChat();
const { scheme } = useAppearance();
const isLightTheme = scheme === 'light';
useEffect(() => {
Notifee.setBadgeCount(0);
const unsubscribes = [onForegroundAndroid(), onForegroundIOS()];
return () => {
unsubscribes.forEach((fn) => fn());
};
}, []);
return (
<NavigationContainer ref={navigationRef} theme={isLightTheme ? DefaultTheme : DarkTheme}>
<RootStack.Navigator screenOptions={{ headerShown: false }}>
{!currentUser ? (
<RootStack.Screen name={Routes.SignIn} component={SignInScreen} />
) : (
<>
<RootStack.Screen name={Routes.Home} component={HomeScreen} />
<RootStack.Screen name={Routes.GroupChannelTabs} component={GroupChannelTabs} />
<RootStack.Screen name={Routes.GroupChannel} component={GroupChannelScreen} />
<RootStack.Screen name={Routes.GroupChannelSettings} component={GroupChannelSettingsScreen} />
<RootStack.Screen name={Routes.GroupChannelCreate} component={GroupChannelCreateScreen} />
<RootStack.Screen name={Routes.GroupChannelInvite} component={GroupChannelInviteScreen} />
<RootStack.Screen name={Routes.GroupChannelMembers} component={GroupChannelMembersScreen} />
<RootStack.Group screenOptions={{ presentation: 'containedModal', headerShown: false }}>
<RootStack.Screen name={Routes.FileViewer} component={FileViewerScreen} />
</RootStack.Group>
<RootStack.Group screenOptions={{ headerShown: true }}>
<RootStack.Screen name={Routes.ThemeColors} component={ThemeColorsScreen} />
<RootStack.Screen name={Routes.Palette} component={PaletteScreen} />
<RootStack.Screen name={Routes.Storybook} component={StorybookScreen} />
</RootStack.Group>
</>
)}
</RootStack.Navigator>
</NavigationContainer>
);
};
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment