Integrating Bubbl Notifications with existing Notifications List on iOS

Bubbl provides the ability, out-of-the-box, to render a prebuilt component that display the device user with the notifications sent to their device. For more information on this see here.

Many apps will already have the ability to display notifications and messages as a list with the current app design. The Bubbl Plugin provides an additional out-of-the-box method to obtain the Bubbl notifications that have been sent to the device, thus allowing these to be integrated into a single combined list as the app developer requires.

Fetching the data

Invoking the getDeliveredNotification function on the Bubbl Plugin will return a list of notifications.

bubbl.getDeliveredNotifications { notifications, error in
  self.isLoading = false
  self.error = error
  self.notifications = notifications ?? [];
}

Full example code

The example code before shows how obtain the list of notifications and render them as an HStack with an custom icon for the different notification types, implemented by the leadingIcon function.

import SwiftUI
import Bubbl
public struct DeliveredNotificationsView: View {
    
    let bubbl: BUMain
    
    @Environment(\.presentationMode) var presentationMode
    
    @State private var notifications: [DeliveredNotification] = []
    @State private var error: Error?
    
    @State private var isLoading = true
    
    public var body: some View {
        NavigationView {
            VStack {
                if (error != nil) {
                  Text("Something went wrong...")
                } else if isLoading {
                    ProgressView()
                        .progressViewStyle(CircularProgressViewStyle())
                        .padding()
                } else if (notifications.isEmpty) {
                    Text("No notifications")
                } else {
                    List(notifications) { notification in
                        HStack(spacing: 16.0) {
                            leadingIcon(for: notification.type)
                            
                            VStack(alignment: .leading) {
                                Text(notification.title ?? "No title")
                                    .font(.headline)
                                Text(formattedDeliveryDate(for: notification.notificationDeliveryDate))
                                    .font(.subheadline)
                                    .foregroundColor(.secondary)
                            }
                        }
                        .onTapGesture {
                            bubbl.show(notification)
                        }
                    }
                }
            }
            .onAppear(perform: loadData)
            .navigationBarTitle("Delivered Notifications")
            .navigationBarTitleDisplayMode(.inline)
            .navigationBarItems(leading: Button(action: {
                self.presentationMode.wrappedValue.dismiss()
            }) {
                Text("Back")
            })
        }
    }
    
    func loadData() {
        // fetch the notifications
        bubbl.getDeliveredNotifications { notifications, error in
            self.isLoading = false
            self.error = error
            self.notifications = notifications ?? [];
        }
    }
    
    private func formattedDeliveryDate(for date: Date) -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
            dateFormatter.dateFormat = "MMM d, yyyy h:mm a"
            return dateFormatter.string(from: date)
    }
    
    private func leadingIcon(for type: String) -> some View {
        switch type {
        case "message":
            return AnyView(Image(systemName: "message"))
        case "survey":
            return AnyView(Image(systemName: "doc.text.magnifyingglass"))
        case "video":
            return AnyView(Image(systemName: "play.circle"))
        case "image":
            return AnyView(Image(systemName: "photo"))
        case "audio":
            return AnyView(Image(systemName: "speaker.wave.2"))
        default:
            return AnyView(EmptyView())
        }
    }
}