Skip to content

Commit 169bb9c

Browse files
Merge branch 'develop' into develop
2 parents ae9bd1f + 2e46ce6 commit 169bb9c

File tree

10 files changed

+1302
-26
lines changed

10 files changed

+1302
-26
lines changed

android/app/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ dependencies {
152152

153153
// For SecureKeystore (EncryptedSharedPreferences)
154154
implementation 'androidx.security:security-crypto:1.1.0'
155+
156+
// For ProcessLifecycleOwner (app foreground detection)
157+
implementation 'androidx.lifecycle:lifecycle-process:2.8.7'
155158
}
156159

157160
apply plugin: 'com.google.gms.google-services'

android/app/src/main/java/chat/rocket/reactnative/notification/CustomPushNotification.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import android.util.Log;
1818

1919
import androidx.annotation.Nullable;
20+
import androidx.lifecycle.Lifecycle;
21+
import androidx.lifecycle.ProcessLifecycleOwner;
2022

2123
import com.google.gson.Gson;
2224

@@ -68,6 +70,14 @@ public CustomPushNotification(Context context, Bundle bundle) {
6870
public static void clearMessages(int notId) {
6971
notificationMessages.remove(Integer.toString(notId));
7072
}
73+
74+
/**
75+
* Checks if the app is currently in the foreground.
76+
* Uses ProcessLifecycleOwner to reliably detect app state.
77+
*/
78+
public static boolean isAppInForeground() {
79+
return ProcessLifecycleOwner.get().getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED);
80+
}
7181

7282
public void onReceived() {
7383
String notId = mBundle.getString("notId");
@@ -228,6 +238,15 @@ private void showNotification(Bundle bundle, Ejson ejson, String notId) {
228238
if (ENABLE_VERBOSE_LOGS) {
229239
Log.d(TAG, "[Before add to notificationMessages] notId=" + notId + ", bundle.message length=" + (bundle.getString("message") != null ? bundle.getString("message").length() : 0) + ", bundle.notificationLoaded=" + bundle.getBoolean("notificationLoaded", false));
230240
}
241+
242+
// Don't show notification if app is in foreground
243+
if (isAppInForeground()) {
244+
if (ENABLE_VERBOSE_LOGS) {
245+
Log.d(TAG, "App is in foreground, skipping native notification");
246+
}
247+
return;
248+
}
249+
231250
notificationMessages.get(notId).add(bundle);
232251
if (ENABLE_VERBOSE_LOGS) {
233252
Log.d(TAG, "[After add] notificationMessages[" + notId + "].size=" + notificationMessages.get(notId).size());
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import React from 'react';
2+
3+
import { ThemeContext, type TSupportedThemes } from '../../theme';
4+
import { themes } from '../../lib/constants/colors';
5+
import NotifierComponent from './NotifierComponent';
6+
import { SubscriptionType } from '../../definitions';
7+
import {
8+
BASE_ROW_HEIGHT,
9+
BASE_ROW_HEIGHT_CONDENSED,
10+
ResponsiveLayoutContext
11+
} from '../../lib/hooks/useResponsiveLayout/useResponsiveLayout';
12+
13+
const responsiveLayoutProviderValue = {
14+
fontScale: 1,
15+
fontScaleLimited: 1,
16+
isLargeFontScale: false,
17+
rowHeight: BASE_ROW_HEIGHT,
18+
rowHeightCondensed: BASE_ROW_HEIGHT_CONDENSED,
19+
width: 300,
20+
height: 800
21+
};
22+
23+
const baseNotification = {
24+
text: 'Hey! How are you doing?',
25+
payload: {
26+
_id: '1',
27+
rid: 'rid-1',
28+
name: 'general',
29+
sender: { username: 'rocket.cat' },
30+
type: SubscriptionType.CHANNEL
31+
},
32+
title: 'general',
33+
avatar: 'rocket.cat'
34+
};
35+
36+
const Wrapper = ({ children, theme = 'light' }: { children: React.ReactNode; theme?: TSupportedThemes }) => (
37+
<ThemeContext.Provider value={{ theme, colors: themes[theme] }}>
38+
<ResponsiveLayoutContext.Provider value={responsiveLayoutProviderValue}>{children}</ResponsiveLayoutContext.Provider>
39+
</ThemeContext.Provider>
40+
);
41+
42+
export default {
43+
title: 'InAppNotification'
44+
};
45+
46+
export const DirectMessage = () => (
47+
<Wrapper>
48+
<NotifierComponent
49+
notification={{
50+
...baseNotification,
51+
payload: {
52+
...baseNotification.payload,
53+
type: SubscriptionType.DIRECT,
54+
sender: { username: 'diego.mello' }
55+
},
56+
title: 'diego.mello',
57+
avatar: 'diego.mello'
58+
}}
59+
/>
60+
</Wrapper>
61+
);
62+
export const ChannelMessage = () => (
63+
<Wrapper>
64+
<NotifierComponent notification={baseNotification} />
65+
</Wrapper>
66+
);
67+
export const WithDarkTheme = () => (
68+
<Wrapper theme='dark'>
69+
<NotifierComponent notification={baseNotification} />
70+
</Wrapper>
71+
);
72+
export const WithBlackTheme = () => (
73+
<Wrapper theme='black'>
74+
<NotifierComponent notification={baseNotification} />
75+
</Wrapper>
76+
);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { generateSnapshots } from '../../../.rnstorybook/generateSnapshots';
2+
import * as stories from './NotifierComponent.stories';
3+
4+
generateSnapshots(stories);

app/containers/InAppNotification/NotifierComponent.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,6 @@ const styles = StyleSheet.create({
4646
flexDirection: 'row',
4747
alignItems: 'center'
4848
},
49-
inner: {
50-
flex: 1
51-
},
5249
avatar: {
5350
marginRight: 10
5451
},
@@ -112,7 +109,7 @@ const NotifierComponent = React.memo(({ notification, isMasterDetail }: INotifie
112109
<Touch style={styles.content} onPress={onPress} hitSlop={BUTTON_HIT_SLOP} testID={`in-app-notification-${text}`}>
113110
<>
114111
<Avatar text={avatar} size={AVATAR_SIZE} type={type} rid={rid} style={styles.avatar} />
115-
<View style={styles.inner}>
112+
<View>
116113
<Text style={[styles.roomName, { color: themes[theme].fontTitlesLabels }]} numberOfLines={1}>
117114
{title}
118115
</Text>

0 commit comments

Comments
 (0)