Skip to content

Latest commit

 

History

History
546 lines (467 loc) · 16.6 KB

Inbox.md

File metadata and controls

546 lines (467 loc) · 16.6 KB
android-inbox-banner

Courier Inbox

An in-app notification center list you can use to notify your users. Allows you to build high quality, flexible notification feeds very quickly.

Requirements

Requirement Reason
Courier Inbox Provider Needed to link your Courier Inbox to the SDK
Authentication Needed to view inbox messages that belong to a user.

Authentication

If you are using JWT authentication, be sure to enable JWT support on the Courier Inbox Provider here.

Screenshot 2024-12-09 at 11 19 31 AM

Theme

Your app theme must use the Material Components parent. This is for Material buttons. Set your themes.xml like this.

<resources>
    <style name="Your.Theme" parent="Theme.MaterialComponents.DayNight.DarkActionBar" />
</resources>

Usage

CourierInbox works with all native Android UI frameworks.

UI Framework Support
XML
Programmatic
Jetpack Compose

Default Inbox Example

The default CourierInbox styles. Colors are using colorPrimary located in your res/values/themes.xml file.

android-default-inbox-styles

Jetpack Compose

CourierInbox(
    modifier = Modifier.padding(innerPadding),
    onClickMessageListener = { message, index ->
        if (message.isRead) message.markAsUnread() else message.markAsRead()
    },
    onLongPressMessageListener = { message, index ->
        message.markAsArchived()
    },
    onClickActionListener = { action, message, index ->
        print(message.toString())
    },
    onScrollInboxListener = { offsetInDp ->
        print(offsetInDp.toString())
    }
)

Android Layouts

<com.courier.android.ui.inbox.CourierInbox xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/courierInbox"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
val inbox: CourierInbox = view.findViewById(R.id.courierInbox)

inbox.setOnClickMessageListener { message, index ->
    Courier.log(message.toString())
    if (message.isRead) message.markAsUnread() else message.markAsRead()
}

inbox.setOnLongPressMessageListener { message, index ->
    Courier.log(message.toString())
}

inbox.setOnClickActionListener { action, message, index ->
    Courier.log(action.toString())
}

inbox.setOnScrollInboxListener { offsetInDp ->
    Courier.log(offsetInDp.toString())
}

Styled Inbox Example

The styles you can use to quickly customize the CourierInbox.

Screenshot 2024-12-09 at 11 19 31 AM

fun getTheme(context: Context): CourierInboxTheme {

    val whiteColor = Color(0xFFFFFFFF).toArgb()
    val blackColor = Color(0xFF000000).toArgb()
    val blackLightColor = Color(0x80000000).toArgb()
    val primaryColor = Color(0xFF6650a4).toArgb()
    val primaryLightColor = Color(0xFF625b71).toArgb()
    val font = ResourcesCompat.getFont(context, R.font.poppins)

    return CourierInboxTheme(
        loadingIndicatorColor = primaryColor,
        tabIndicatorColor = primaryColor,
        tabStyle = CourierStyles.Inbox.TabStyle(
            selected = CourierStyles.Inbox.TabItemStyle(
                font = CourierStyles.Font(
                    typeface = font,
                    sizeInSp = 18,
                    color = primaryColor
                ),
                indicator = CourierStyles.Inbox.TabIndicatorStyle(
                    font = CourierStyles.Font(
                        typeface = font,
                        sizeInSp = 14,
                        color = whiteColor
                    ),
                    color = primaryColor
                )
            ),
            unselected = CourierStyles.Inbox.TabItemStyle(
                font = CourierStyles.Font(
                    typeface = font,
                    sizeInSp = 18,
                    color = blackLightColor,
                ),
                indicator = CourierStyles.Inbox.TabIndicatorStyle(
                    font = CourierStyles.Font(
                        typeface = font,
                        sizeInSp = 14,
                        color = whiteColor
                    ),
                    color = blackLightColor,
                )
            )
        ),
        readingSwipeActionStyle = CourierStyles.Inbox.ReadingSwipeActionStyle(
            read = CourierStyles.Inbox.SwipeActionStyle(
                color = primaryColor
            ),
            unread = CourierStyles.Inbox.SwipeActionStyle(
                color = primaryLightColor
            )
        ),
        archivingSwipeActionStyle = CourierStyles.Inbox.ArchivingSwipeActionStyle(
            CourierStyles.Inbox.SwipeActionStyle(
                color = primaryColor
            )
        ),
        unreadIndicatorStyle = CourierStyles.Inbox.UnreadIndicatorStyle(
            indicator = CourierStyles.Inbox.UnreadIndicator.DOT,
            color = primaryColor
        ),
        titleStyle = CourierStyles.Inbox.TextStyle(
            unread = CourierStyles.Font(
                typeface = font,
                color = blackColor,
                sizeInSp = 18
            ),
            read = CourierStyles.Font(
                typeface = font,
                color = blackColor,
                sizeInSp = 18
            ),
        ),
        bodyStyle = CourierStyles.Inbox.TextStyle(
            unread = CourierStyles.Font(
                typeface = font,
                color = blackLightColor,
                sizeInSp = 16
            ),
            read = CourierStyles.Font(
                typeface = font,
                color = blackLightColor,
                sizeInSp = 16
            )
        ),
        timeStyle = CourierStyles.Inbox.TextStyle(
            unread = CourierStyles.Font(
                typeface = font,
                color = blackColor,
                sizeInSp = 14
            ),
            read = CourierStyles.Font(
                typeface = font,
                color = blackColor,
                sizeInSp = 14
            )
        ),
        infoViewStyle = CourierStyles.InfoViewStyle(
            font = CourierStyles.Font(
                typeface = font,
                color = blackColor,
                sizeInSp = 18
            ),
            button = CourierStyles.Button(
                font = CourierStyles.Font(
                    typeface = font,
                    color = whiteColor,
                    sizeInSp = 16
                ),
                backgroundColor = primaryColor,
                cornerRadiusInDp = 100
            )
        ),
        buttonStyle = CourierStyles.Inbox.ButtonStyle(
            unread = CourierStyles.Button(
                font = CourierStyles.Font(
                    typeface = font,
                    color = whiteColor,
                    sizeInSp = 16
                ),
                backgroundColor = primaryColor,
                cornerRadiusInDp = 100
            ),
            read = CourierStyles.Button(
                font = CourierStyles.Font(
                    typeface = font,
                    color = whiteColor,
                    sizeInSp = 16
                ),
                backgroundColor = primaryColor,
                cornerRadiusInDp = 100
            )
        ),
        dividerItemDecoration = DividerItemDecoration(context, DividerItemDecoration.VERTICAL)
    )
}

Jetpack Compose

CourierInbox(
    modifier = Modifier.padding(innerPadding),
    canSwipePages = true,
    lightTheme = getTheme(context),
    darkTheme = getTheme(context),
    ..
)

Android Layouts

val inbox: CourierInbox = view.findViewById(R.id.courierInbox)
inbox.canSwipePages = true
inbox.lightTheme = getTheme(context)
inbox.darkTheme = getTheme(context)
inbox..

Courier Studio Branding (Optional)

setting

You can control your branding from the Courier Studio.

Supported Brand Styles Support
Primary Color
Show/Hide Courier Footer

👋 Branding APIs can be found here

Custom Inbox Example

The raw data you can use to build any UI you'd like.

class CustomInboxFragment: Fragment(R.layout.fragment_custom_inbox) {

    ..

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        ..

        // Setup the listener
        inboxListener = Courier.shared.addInboxListener(
            onLoading = { isRefresh ->
                // Called when listener is registered, refreshing or restarting
            },
            onError = { e ->
                // Called on error or sign out
            },
            onUnreadCountChanged = { count ->
                // Will return 0 when a user is signed out
            },
            onFeedChanged = { messageSet ->
                // Called when the feed initially loads or is restarted from scratch
            },
            onArchiveChanged = { messageSet ->
                // Called when the feed initially loads or is restarted from scratch
            },
            onPageAdded = { feed, messageSet ->
                // Called when pagination happens
            },
            onMessageChanged = { feed, index, message ->
                // Called when a message is change (i.e. read / unread)
            },
            onMessageAdded = { feed, index, message ->
                // Called when a message is added (i.e. new message received in realtime)
            },
            onMessageRemoved = { feed, index, message ->
                // Called when a message is removed (i.e. message is archived)
            }
        )

    }
    
    override fun onDestroyView() {
        super.onDestroyView()
        inboxListener.remove()
    }

}

Full Examples

Link Style
Default Example Default
Styled Example Styled
Custom Example Custom

Available Properties and Functions

// Listen to all inbox events
// Only one "pipe" of data is created behind the scenes for network / performance reasons
val inboxListener = Courier.shared.addInboxListener(
    onLoading = { isRefresh ->
        // Called when listener is registered, refreshing or restarting
    },
    onError = { e ->
        // Called on error or sign out
    },
    onUnreadCountChanged = { count ->
        // Will return 0 when a user is signed out
    },
    onFeedChanged = { messageSet ->
        // Called when the feed initially loads or is restarted from scratch
    },
    onArchiveChanged = { messageSet ->
        // Called when the feed initially loads or is restarted from scratch
    },
    onPageAdded = { feed, messageSet ->
        // Called when pagination happens
    },
    onMessageChanged = { feed, index, message ->
        // Called when a message is change (i.e. read / unread)
    },
    onMessageAdded = { feed, index, message ->
        // Called when a message is added (i.e. new message received in realtime)
    },
    onMessageRemoved = { feed, index, message ->
        // Called when a message is removed (i.e. message is archived)
    }
)

// Stop the current listener
inboxListener.remove()

// Remove all listeners
// This will also remove the listener of the prebuilt UI
Courier.shared.removeAllInboxListeners()

// The amount of inbox messages to fetch at a time
// Will affect prebuilt UI
Courier.shared.inboxPaginationLimit = 123

// The available messages the inbox has
val inboxMessages = Courier.shared.inboxMessages

lifecycle.coroutineScope.launch {

    // Fetches the next page of messages
    Courier.shared.fetchNextPageOfMessages()

    // Reloads the inbox
    // Commonly used with pull to refresh
    Courier.shared.refreshInbox()

    // Reads all the messages
    // Writes the update instantly and performs request in background
    try await Courier.shared.readAllInboxMessages()

}

// Inbox Message functions
lifecycle.coroutineScope.launch {
    val messageId = "asdf"
    Courier.shared.openMessage(messageId = messageId)
    Courier.shared.clickMessage(messageId = messageId)
    Courier.shared.readMessage(messageId = messageId)
    Courier.shared.unreadMessage(messageId = messageId)
    Courier.shared.archiveMessage(messageId = messageId)
}

// Extensions
let message = InboxMessage(..)
message.markAsOpened()
message.markAsRead()
message.markAsUnread()
message.markAsClicked()
message.markAsArchived()

// Clicking an action
message.actions?.first?.markAsClicked()

👋 Inbox APIs can be found here