Skip to content

Latest commit

 

History

History
421 lines (367 loc) · 11.3 KB

File metadata and controls

421 lines (367 loc) · 11.3 KB
banner-flutter-inbox

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.

JWT 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

Default Inbox Example

The default CourierInbox styles.

default-inbox-styles android-default-inbox-styles
CourierInbox(
  onMessageClick: (message, index) {
    message.isRead ? message.markAsUnread() : message.markAsRead();
  },
  onActionClick: (action, message, index) {
    print(action);
  },
)

⚠️ Courier Flutter will automatically use your app's Theme unless you specifically apply a CourierTheme. Here are the values that will automatically be used by your Theme.

  • Button Style = Theme.of(context).elevatedButtonTheme.style
  • Loading Indicator Color = Theme.of(context).primaryColor
  • Unread Indicator Color = Theme.of(context).primaryColor
  • Title Style = Theme.of(context).textTheme.titleMedium
  • Body Style = Theme.of(context).textTheme.bodyMedium
  • Time Style = Theme.of(context).textTheme.labelMedium
  • Empty / Error State Text Style = Theme.of(context).textTheme.titleMedium
  • Empty / Error State Button Style = Theme.of(context).elevatedButtonTheme.style

Styled Inbox Example

The styles you can use to quickly customize the CourierInbox.

default-inbox-styles android-default-inbox-styles
final theme = CourierInboxTheme(
    unreadIndicatorStyle: const CourierInboxUnreadIndicatorStyle(
      indicator: CourierInboxUnreadIndicator.dot,
      color: Color(0xFF9747FF),
    ),
    loadingIndicatorColor: Color(0xFF9747FF),
    tabIndicatorColor: Color(0xFF9747FF),
    tabStyle: CourierInboxTabStyle(
      selected: CourierInboxTabItemStyle(
        font: GoogleFonts.sen().copyWith(
          fontWeight: FontWeight.bold,
          fontSize: 18,
          color: Color(0xFF9747FF),
        ),
        indicator: CourierInboxTabIndicatorStyle(
          color: Color(0xFF9747FF),
          font: GoogleFonts.sen().copyWith(
            fontWeight: FontWeight.normal,
            fontSize: 16,
            color: Colors.white,
          ),
        ),
      ),
      unselected: CourierInboxTabItemStyle(
        font: GoogleFonts.sen().copyWith(
          fontWeight: FontWeight.normal,
          fontSize: 18,
          color: Colors.black45,
        ),
        indicator: CourierInboxTabIndicatorStyle(
          color: Colors.black45,
          font: GoogleFonts.sen().copyWith(
            fontWeight: FontWeight.normal,
            fontSize: 16,
            color: Colors.white,
          ),
        ),
      ),
    ),
    readingSwipeActionStyle: CourierInboxReadingSwipeActionStyle(
      read: const CourierInboxSwipeActionStyle(
        icon: Icons.drafts,
        color: Color(0xFF9747FF),
      ),
      unread: CourierInboxSwipeActionStyle(
        icon: Icons.mark_email_read,
        color: Color(0xFF9747FF).withOpacity(0.5),
      ),
    ),
    archivingSwipeActionStyle: const CourierInboxArchivingSwipeActionStyle(
      archive: CourierInboxSwipeActionStyle(
        icon: Icons.inbox,
        color: Colors.red,
      ),
    ),
    titleStyle: CourierInboxTextStyle(
      read: GoogleFonts.sen().copyWith(
        fontWeight: FontWeight.normal,
        fontSize: 18,
      ),
      unread: GoogleFonts.sen().copyWith(
        fontWeight: FontWeight.bold,
        fontSize: 18,
      ),
    ),
    timeStyle: CourierInboxTextStyle(
      read: GoogleFonts.sen().copyWith(
        fontWeight: FontWeight.normal,
        fontSize: 16,
      ),
      unread: GoogleFonts.sen().copyWith(
        fontWeight: FontWeight.bold,
        fontSize: 16,
      ),
    ),
    bodyStyle: CourierInboxTextStyle(
      read: GoogleFonts.sen().copyWith(
        fontWeight: FontWeight.normal,
        fontSize: 16,
      ),
      unread: GoogleFonts.sen().copyWith(
        fontWeight: FontWeight.bold,
        fontSize: 16,
      ),
    ),
    buttonStyle: CourierInboxButtonStyle(
      read: FilledButton.styleFrom(
        backgroundColor: Colors.grey,
        foregroundColor: Colors.white,
        textStyle: GoogleFonts.sen().copyWith(
          fontWeight: FontWeight.normal,
          fontSize: 16,
        ),
      ),
      unread: FilledButton.styleFrom(
        backgroundColor: Color(0xFF9747FF),
        foregroundColor: Colors.white,
        textStyle: GoogleFonts.sen().copyWith(
          fontWeight: FontWeight.normal,
          fontSize: 16,
        ),
      ),
    ),
    separator: null,
);

// Pass the theme to the inbox
// This example will use the same theme for light and dark mode
CourierInbox(
  canSwipePages: true,
  lightTheme: theme,
  darkTheme: theme,
  scrollController: _customScrollController,
  onMessageClick: (message, index) {
    message.isRead ? message.markAsUnread() : message.markAsRead();
  },
  onActionClick: (action, message, index) {
    print(action);
  },
  onMessageLongPress: (message, index) {
    print(message);
  },
  onError: (error) {
    print(error);
    return 'Your custom error message';
  }
)
...

Custom Inbox Example

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

item
late CourierInboxListener _inboxListener;
bool _isLoading = true;
String? _error;
List<InboxMessage> _messages = [];
bool _canLoadMore = false;

_inboxListener = await Courier.shared.addInboxListener(
  onLoading: (isRefresh) {
    setState(() {
      if (!isRefresh) _isLoading = true;
      _error = null;
    });
  },
  onError: (error) {
    setState(() {
      _isLoading = false;
      _error = error;
    });
  },
  onUnreadCountChanged: (unreadCount) {
    print('unreadCount: $unreadCount');
  },
  onTotalCountChanged: (feed, totalCount) {
    print('totalCount: $totalCount');
  },
  onMessagesChanged: (messages, canPaginate, feed) {
    if (feed == InboxFeed.feed) {
      setState(() {
        _messages = messages;
        _isLoading = false;
        _error = null;
        _canLoadMore = canPaginate;
      });
    }
  },
  onPageAdded: (messages, canPaginate, isFirstPage, feed) {
    if (feed == InboxFeed.feed && !isFirstPage) {
      setState(() {
        _messages = messages;
        _isLoading = false;
        _error = null;
        _canLoadMore = canPaginate;
      });
    }
  },
  onMessageEvent: (message, index, feed, event) {
    switch (event) {
      case InboxMessageEvent.added:
        setState(() {
          _messages.insert(index, message);
        });
        break;
      case InboxMessageEvent.read:
        setState(() {
          _messages[index] = message;
        });
        break;
      case InboxMessageEvent.unread:
        setState(() {
          _messages[index] = message;
        });
        break;
      case InboxMessageEvent.opened:
        setState(() {
          _messages[index] = message;
        });
        break;
      case InboxMessageEvent.archived:
        setState(() {
          _messages.removeAt(index);
        });
        break;
      case InboxMessageEvent.clicked:
        setState(() {
          _messages[index] = message;
        });
        break;
    }
  },
);

..

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: ListView.separated(
      itemCount: _messages.length,
      itemBuilder: (BuildContext context, int index) {
        final message = _messages[index];
        return Text(message.messageId)
      },
    ),
  );
}

..

@override
void dispose() {
  _inboxListener.remove().catchError((error) {
    print('Failed to remove inbox listener: $error');
  });
  super.dispose();
}

Full Examples

Link
Examples

Available Properties and Functions

// Pagination
await Courier.shared.setInboxPaginationLimit(limit: 100);
final messages = await Courier.shared.fetchNextInboxPage();

// Currently fetched messages
final messages = await Courier.shared.inboxMessages;

// Pull to refresh
await Courier.shared.refreshInbox();

// Update a message
await Courier.shared.openMessage(messageId: messageId);
await Courier.shared.readMessage(messageId: messageId);
await Courier.shared.unreadMessage(messageId: messageId);
await Courier.shared.clickMessage(messageId: messageId);
await Courier.shared.archiveMessage(messageId: messageId);
await Courier.shared.readAllInboxMessages();

// Update message shortcuts
final message = InboxMessage(...);
await message.markAsOpened();
await message.markAsRead();
await message.markAsUnread();
await message.markAsClicked();
await message.markAsArchived();

// Listener
final inboxListener = await Courier.shared.addInboxListener(
  onLoading: (isRefresh) {
    
  },
  onError: (error) {
    
  },
  onUnreadCountChanged: (unreadCount) {
    
  },
  onTotalCountChanged: (feed, totalCount) {
    
  },
  onMessagesChanged: (messages, canPaginate, feed) {
    
  },
  onPageAdded: (messages, canPaginate, isFirstPage, feed) {
    
  },
  onMessageEvent: (message, index, feed, event) {
    
  },
);

await inboxListener.remove();

👋 Inbox APIs can be found here