Notification indicator in native Tab Bar #242
-
|
Hi, we would like to use native Tab Bar, but one of our tabs is Notifications, which shows number of notifications on it. Thanks for any help! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
|
We managed to do this using bridge component, inspired by the Ruby friends authentication video by @joemasilotti . On Swift side it looks like this: // Components/ConfigurationComponent.swift
import HotwireNative
import UIKit
import WebKit
final class ConfigurationComponent: BridgeComponent {
nonisolated override class var name: String { "configuration" }
private var viewController: UIViewController? {
delegate?.destination as? UIViewController
}
private var tabBarController: HotwireTabBarController? {
viewController?.tabBarController as? HotwireTabBarController
}
override func onReceive(message: Message) {
guard let data: MessageData = message.data() else { return }
setNotificationIndicator(count: data.notification_count)
setIndicator(indicator: data.indicator)
setIconBadge(count: data.total_notification_count)
}
func setNotificationIndicator(count: String) {
guard let items = tabBarController?.tabBar.items, items.count > 1 else { return }
let targetTab = items[1]
let oldValue = targetTab.badgeValue
let valueUnchanged = count == oldValue || (oldValue == nil && count == "0")
if valueUnchanged { return }
//print(valueUnchanged)
if (count == "0"){
targetTab.badgeValue = nil
} else {
targetTab.badgeColor = .purple
targetTab.badgeValue = count
}
// if count changed, we want to reload the tab showing notifications
let tab_reporter_navigator = tabBarController?.navigator(for: HotwireTab.reporter)
tab_reporter_navigator?.reload()
}
func setIndicator(indicator: String) {
guard let items = tabBarController?.tabBar.items, items.count > 4 else { return }
let targetTab = items[4]
//print(indicator)
let valueUnchanged = (indicator == "true" && targetTab.badgeValue == "") || (indicator == "false" && targetTab.badgeValue == nil)
if valueUnchanged { return }
//print("indicator changed")
if (indicator == "true"){
targetTab.badgeColor = .purple
targetTab.badgeValue = ""
} else {
targetTab.badgeValue = nil
}
//print("reloading")
let tab_other_navigator = tabBarController?.navigator(for: HotwireTab.other)
tab_other_navigator?.reload()
}
func setIconBadge(count: String) {
let center = UNUserNotificationCenter.current()
if count == "0" {
center.setBadgeCount(0)
} else {
center.setBadgeCount(Int(count)!)
}
}
}
private extension ConfigurationComponent {
struct MessageData: Decodable {
let notification_count: String
let indicator: String
let total_notification_count: String
}
}and ...
//Models/Tabs.swift
extension HotwireTab {
static let all = [
dashboardTab,
reporterTab,
eventsTab,
announcementsTab,
otherTab
]
static let unauthenticated = [
nativeStartTab
]
// these are used for reloading navigator in ConfigurationComponent
static let reporter = reporterTab
static let other = otherTab
}On the stimulus side, we just send all the data. I'm very new to Swift and Hotwire Native, so maybe this can be done more elegantly, or there are some problems with this approach, but from manual testing, it seems to work. |
Beta Was this translation helpful? Give feedback.
We managed to do this using bridge component, inspired by the Ruby friends authentication video by @joemasilotti .
On Swift side it looks like this: