Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion examples/SampleApp/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,9 @@ const App = () => {
messageListImplementationStoredValue?.id as MessageListImplementationConfigItem['id'],
);
setMessageListMode(messageListModeStoredValue?.mode as MessageListModeConfigItem['mode']);
setMessageListPruning(messageListPruningStoredValue?.value as MessageListPruningConfigItem['value']);
setMessageListPruning(
messageListPruningStoredValue?.value as MessageListPruningConfigItem['value'],
);
};
getMessageListConfig();
return () => {
Expand Down
1 change: 1 addition & 0 deletions examples/SampleApp/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'react-native-gesture-handler';
import { AppRegistry } from 'react-native';
import { enableScreens } from 'react-native-screens';
import './src/utils/bootstrapBackgroundMessageHandler';

import App from './App';
import { name as appName } from './app.json';
Expand Down
90 changes: 46 additions & 44 deletions examples/SampleApp/ios/SampleApp-tvOS/Info.plist
Original file line number Diff line number Diff line change
@@ -1,53 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.0.22</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>28</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.0.22</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>28</string>
<key>LSRequiresIPhoneOS</key>
<true />
<key>NSAppTransportSecurity</key>
<key>NSExceptionDomains</key>
<dict>
<key>NSExceptionDomains</key>
<key>localhost</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true />
</dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false />
</dict>
</plist>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>RCTNewArchEnabled</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
121 changes: 64 additions & 57 deletions examples/SampleApp/ios/SampleApp/Info.plist
Original file line number Diff line number Diff line change
@@ -1,62 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>ChatSample</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.11.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>154</string>
<key>FirebaseAppDelegateProxyEnabled</key>
<true/>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>ChatSample</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.11.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>154</string>
<key>FirebaseAppDelegateProxyEnabled</key>
<true />
<key>ITSAppUsesNonExemptEncryption</key>
<false />
<key>LSRequiresIPhoneOS</key>
<true />
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false />
<key>NSAllowsLocalNetworking</key>
<true />
</dict>
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) would like to use your camera to share image in a message.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>$(PRODUCT_NAME) would like share live location always in a message.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>$(PRODUCT_NAME) would like share live location when in use in a message.</string>
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) would like to use your microphone for voice recording.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>$(PRODUCT_NAME) would like access to your photo gallery to share image in a message.</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false />
<key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
</plist>
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) would like to use your camera to share image in a message.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>$(PRODUCT_NAME) would like share live location always in a message.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>$(PRODUCT_NAME) would like share live location when in use in a message.</string>
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) would like to use your microphone for voice recording.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>$(PRODUCT_NAME) would like access to your photo gallery to share image in a message.</string>
<key>RCTNewArchEnabled</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
56 changes: 31 additions & 25 deletions examples/SampleApp/src/hooks/useChatClient.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { useEffect, useRef, useState } from 'react';
import { StreamChat, PushProvider } from 'stream-chat';
import { getMessaging, AuthorizationStatus } from '@react-native-firebase/messaging';
import {
getMessaging,
AuthorizationStatus,
FirebaseMessagingTypes,
} from '@react-native-firebase/messaging';
import notifee from '@notifee/react-native';
import { SqliteClient } from 'stream-chat-react-native';
import { USER_TOKENS, USERS } from '../ChatUsers';
Expand All @@ -11,6 +15,30 @@ import { PermissionsAndroid, Platform } from 'react-native';

const messaging = getMessaging();

const displayNotification = async (
remoteMessage: FirebaseMessagingTypes.RemoteMessage,
channelId: string,
) => {
const { stream, ...rest } = remoteMessage.data ?? {};
const data = {
...rest,
...((stream as unknown as Record<string, string> | undefined) ?? {}), // extract and merge stream object if present
};
if (data.body && data.title) {
await notifee.displayNotification({
android: {
channelId,
pressAction: {
id: 'default',
},
},
body: data.body as string,
title: data.title as string,
data,
});
}
};

// Request Push Notification permission from device.
const requestNotificationPermission = async () => {
const authStatus = await messaging.requestPermission();
Expand Down Expand Up @@ -94,34 +122,12 @@ export const useChatClient = () => {
});
// show notifications when on foreground
const unsubscribeForegroundMessageReceive = messaging.onMessage(async (remoteMessage) => {
const { stream, ...rest } = remoteMessage.data ?? {};
const data = {
...rest,
...((stream as unknown as Record<string, string> | undefined) ?? {}), // extract and merge stream object if present
};
const channelId = await notifee.createChannel({
id: 'foreground',
name: 'Foreground Messages',
});
// create the android channel to send the notification to
// display the notification on foreground
const notification = remoteMessage.notification ?? {};
const body = (data.body ?? notification.body) as string;
const title = (data.title ?? notification.title) as string;

if (body && title) {
await notifee.displayNotification({
android: {
channelId,
pressAction: {
id: 'default',
},
},
body,
title,
data,
});
}

await displayNotification(remoteMessage, channelId);
});

unsubscribePushListenersRef.current = () => {
Expand Down
71 changes: 71 additions & 0 deletions examples/SampleApp/src/utils/bootstrapBackgroundMessageHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { LoginConfig } from '../types';
import AsyncStore from './AsyncStore';
import {
FirebaseMessagingTypes,
setBackgroundMessageHandler,
} from '@react-native-firebase/messaging';
import { DeliveredMessageConfirmation, StreamChat } from 'stream-chat';
import notifee from '@notifee/react-native';
import { getMessaging } from '@react-native-firebase/messaging';

const messaging = getMessaging();

const displayNotification = async (
remoteMessage: FirebaseMessagingTypes.RemoteMessage,
channelId: string,
) => {
const { stream, ...rest } = remoteMessage.data ?? {};
const data = {
...rest,
...((stream as unknown as Record<string, string> | undefined) ?? {}), // extract and merge stream object if present
};
if (data.body && data.title) {
await notifee.displayNotification({
android: {
channelId,
pressAction: {
id: 'default',
},
},
body: data.body as string,
title: data.title as string,
data,
});
}
};

setBackgroundMessageHandler(messaging, async (remoteMessage) => {
try {
const loginConfig = await AsyncStore.getItem<LoginConfig>(
'@stream-rn-sampleapp-login-config',
null,
);
if (!loginConfig) {
return;
}
const chatClient = StreamChat.getInstance(loginConfig.apiKey);
await chatClient._setToken({ id: loginConfig.userId }, loginConfig.userToken);

const notification = remoteMessage.data;

const deliverMessageConfirmation = [
{
cid: notification?.cid,
id: notification?.id,
},
];

await chatClient?.markChannelsDelivered({
latest_delivered_messages: deliverMessageConfirmation as DeliveredMessageConfirmation[],
});
// create the android channel to send the notification to
const channelId = await notifee.createChannel({
id: 'chat-messages',
name: 'Chat Messages',
});
// display the notification
await displayNotification(remoteMessage, channelId);
} catch (error) {
console.error(error);
}
});
Loading
Loading