Skip to content
1 change: 1 addition & 0 deletions example/src/components/App/App.constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Route } from '../../constants';

export const routeIcon = {
[Route.Inbox]: 'mail-outline',
[Route.User]: 'person-outline',
};
51 changes: 50 additions & 1 deletion example/src/components/App/Main.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,42 @@
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { useState, useEffect } from 'react';

import { Iterable } from '@iterable/react-native-sdk';

import { colors, Route } from '../../constants';
import type { MainScreenParamList } from '../../types';
import { routeIcon } from './App.constants';
import { getIcon } from './App.utils';
import { User } from '../User';
import Inbox from '../Inbox';
import { useIterableApp } from '../../hooks';

const Tab = createBottomTabNavigator<MainScreenParamList>();

export const Main = () => {
const {
isInboxTab,
isLoggedIn,
loginInProgress,
returnToInboxTrigger,
setIsInboxTab,
setReturnToInboxTrigger,
userId,
} = useIterableApp();
const [unreadMessageCount, setUnreadMessageCount] = useState<number>(0);

useEffect(() => {
if (loginInProgress) return;
if (isLoggedIn) {
Iterable.inAppManager.getMessages().then((messages) => {
setUnreadMessageCount(messages.length);
});
} else {
// Reset unread message count when user logs out
setUnreadMessageCount(0);
}
}, [isLoggedIn, loginInProgress, userId]);

return (
<>
<Tab.Navigator
Expand All @@ -22,7 +50,28 @@ export const Main = () => {
};
}}
>
<Tab.Screen name={Route.User} component={User} />
<Tab.Screen
name={Route.Inbox}
component={Inbox}
options={
unreadMessageCount ? { tabBarBadge: unreadMessageCount } : {}
}
listeners={() => ({
tabPress: () => {
if (isInboxTab) {
setReturnToInboxTrigger(!returnToInboxTrigger);
}
setIsInboxTab(true);
},
})}
/>
<Tab.Screen
name={Route.User}
component={User}
listeners={() => ({
tabPress: () => setIsInboxTab(false),
})}
/>
</Tab.Navigator>
</>
);
Expand Down
68 changes: 68 additions & 0 deletions example/src/components/Inbox/Inbox.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
export const iterableInboxCustomization = {
navTitle: 'Iterable',
noMessagesTitle: 'No messages today',
noMessagesBody: 'Come back later',

unreadIndicatorContainer: {
flexDirection: 'column',
justifyContent: 'flex-start',
},

unreadIndicator: {
width: 15,
height: 15,
borderRadius: 15 / 2,
backgroundColor: 'orange',
marginLeft: 10,
marginRight: 10,
marginTop: 10,
},

unreadMessageIconContainer: {
paddingLeft: 0,
flexDirection: 'column',
justifyContent: 'center',
},

readMessageIconContainer: {
paddingLeft: 35,
flexDirection: 'column',
justifyContent: 'center',
},

messageContainer: {
paddingLeft: 10,
width: '65%',
flexDirection: 'column',
justifyContent: 'center',
},

title: {
fontSize: 22,
paddingBottom: 10,
},

body: {
fontSize: 15,
color: 'lightgray',
width: '65%',
flexWrap: 'wrap',
paddingBottom: 10,
},

createdAt: {
fontSize: 12,
color: 'lightgray',
},

messageRow: {
flexDirection: 'row',
backgroundColor: 'white',
paddingTop: 10,
paddingBottom: 10,
height: 200,
borderStyle: 'solid',
borderColor: 'red',
borderTopWidth: 1,
},
};
21 changes: 21 additions & 0 deletions example/src/components/Inbox/Inbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {
IterableInbox,
type IterableInboxProps,
} from '@iterable/react-native-sdk';

import { useIterableApp } from '../../hooks';
import { iterableInboxCustomization } from './Inbox.constants';

export const Inbox = (props: IterableInboxProps) => {
const { returnToInboxTrigger } = useIterableApp();

return (
<IterableInbox
returnToInboxTrigger={returnToInboxTrigger}
customizations={iterableInboxCustomization}
{...props}
/>
);
};

export default Inbox;
2 changes: 2 additions & 0 deletions example/src/components/Inbox/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './Inbox';
export { default } from './Inbox';
1 change: 1 addition & 0 deletions example/src/constants/routes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export enum Route {
Inbox = 'Inbox',
Login = 'Login',
Main = 'Main',
User = 'User',
Expand Down
21 changes: 20 additions & 1 deletion example/src/hooks/useIterableApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ interface IterableAppProps {
initialize: (navigation: Navigation) => void;
/** Whether the SDK has been initialized */
isInitialized?: boolean;
/** Is the tab in focus the `Inbox` tab? */
isInboxTab: boolean;
/** Whether the user is logged in */
isLoggedIn?: boolean;
/**
Expand All @@ -45,10 +47,16 @@ interface IterableAppProps {
loginInProgress?: boolean;
/** Logs the user out */
logout: () => void;
/** TODO: Ask @evantk91 or @Ayyanchira what this is for */
returnToInboxTrigger: boolean;
/** Sets the API key for the user */
setApiKey: (value: string) => void;
/** Sets whether the tab in focus is the `Inbox` tab */
setIsInboxTab: (value: boolean) => void;
/** Sets whether the login is in progress */
setLoginInProgress: (value: boolean) => void;
/** TODO: Ask @evantk91 or @Ayyanchira what this is for */
setReturnToInboxTrigger: (value: boolean) => void;
/** Sets the user ID for the user */
setUserId: (value: string) => void;
/** The user ID for the user */
Expand All @@ -59,13 +67,17 @@ const IterableAppContext = createContext<IterableAppProps>({
apiKey: undefined,
config: null,
initialize: () => undefined,
isInboxTab: false,
isInitialized: false,
isLoggedIn: false,
login: () => undefined,
loginInProgress: false,
logout: () => undefined,
returnToInboxTrigger: false,
setApiKey: () => undefined,
setIsInboxTab: () => undefined,
setLoginInProgress: () => undefined,
setReturnToInboxTrigger: () => undefined,
setUserId: () => undefined,
userId: undefined,
});
Expand All @@ -75,6 +87,9 @@ const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
export const IterableAppProvider: FunctionComponent<
React.PropsWithChildren<unknown>
> = ({ children }) => {
const [returnToInboxTrigger, setReturnToInboxTrigger] =
useState<boolean>(false);
const [isInboxTab, setIsInboxTab] = useState<boolean>(false);
const [itblConfig, setItblConfig] = useState<IterableConfig | null>(null);
const [isLoggedIn, setIsLoggedIn] = useState<boolean>(false);
const [isInitialized, setIsInitialized] = useState<boolean>(false);
Expand Down Expand Up @@ -110,7 +125,7 @@ export const IterableAppProvider: FunctionComponent<
config.inAppDisplayInterval = 1.0; // Min gap between in-apps. No need to set this in production.

config.urlHandler = (url: string) => {
const routeNames = [Route.User];
const routeNames = [Route.Inbox, Route.User];
for (const route of routeNames) {
if (url.includes(route.toLowerCase())) {
// TODO: Figure out typing for this
Expand Down Expand Up @@ -191,13 +206,17 @@ export const IterableAppProvider: FunctionComponent<
apiKey,
config: itblConfig,
initialize,
isInboxTab,
isInitialized,
isLoggedIn,
login,
loginInProgress,
logout,
returnToInboxTrigger,
setApiKey,
setIsInboxTab,
setLoginInProgress,
setReturnToInboxTrigger,
setUserId,
userId,
}}
Expand Down
1 change: 1 addition & 0 deletions example/src/types/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { StackScreenProps } from '@react-navigation/stack';
import { Route } from '../constants/routes';

export type MainScreenParamList = {
[Route.Inbox]: undefined;
[Route.User]: undefined;
};

Expand Down
6 changes: 3 additions & 3 deletions src/IterableInbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ const RNIterableAPI = NativeModules.RNIterableAPI;
const RNEventEmitter = new NativeEventEmitter(RNIterableAPI);

// TODO: Comment
type InboxProps = {
export interface IterableInboxProps {
returnToInboxTrigger?: boolean;
messageListItemLayout?: Function;
customizations?: IterableInboxCustomizations;
tabBarHeight?: number;
tabBarPadding?: number;
safeAreaMode?: boolean;
showNavTitle?: boolean;
};
}

// TODO: Comment
export const IterableInbox = ({
Expand All @@ -49,7 +49,7 @@ export const IterableInbox = ({
tabBarPadding = 20,
safeAreaMode = true,
showNavTitle = true,
}: InboxProps) => {
}: IterableInboxProps) => {
const defaultInboxTitle = 'Inbox';
const inboxDataModel = new IterableInboxDataModel();

Expand Down
2 changes: 1 addition & 1 deletion src/IterableInboxMessageDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ export const IterableInboxMessageDisplay = ({
}}
>
<View style={returnButton}>
<Icon name="ios-chevron-back" style={returnButtonIcon} />
<Icon name="chevron-back-outline" style={returnButtonIcon} />
<Text style={returnButtonText}>Inbox</Text>
</View>
</TouchableWithoutFeedback>
Expand Down
4 changes: 1 addition & 3 deletions src/IterableInboxMessageList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,7 @@ export const IterableInboxMessageList = ({
swipingCheck={setSwiping}
messageListItemLayout={messageListItemLayout}
deleteRow={(messageId: string) => deleteRow(messageId)}
handleMessageSelect={(messageId: string, i: number) =>
handleMessageSelect(messageId, i)
}
handleMessageSelect={handleMessageSelect}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats the reason for this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleanliness/readability.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha. Can the same be done for deleteRow?

contentWidth={contentWidth}
isPortrait={isPortrait}
/>
Expand Down
7 changes: 6 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
*/
export type { InboxImpressionRowInfo } from './InboxImpressionRowInfo';
export type { InboxRowViewModel } from './InboxRowViewModel';
export { Iterable, IterableCommerceItem } from './Iterable';
export {
Iterable,
IterableAttributionInfo,
IterableCommerceItem,
} from './Iterable';
export {
IterableAction,
IterableActionContext,
Expand All @@ -27,6 +31,7 @@ export {
} from './IterableInAppClasses';
export { IterableInAppManager } from './IterableInAppManager';
export { IterableInAppMessage } from './IterableInAppMessage';
export { IterableInbox, type IterableInboxProps } from './IterableInbox';
export type { IterableInboxCustomizations } from './IterableInboxCustomizations';
export { IterableInboxEmptyState } from './IterableInboxEmptyState';
export { IterableInboxMessageCell } from './IterableInboxMessageCell';
Expand Down
Loading