Use markNotificationTraySeen() to update the trayβs seen timestamp on the server when the user visits the Notification Tray screen.This method supports global-level read tracking, separate from per-item seen state. Once invoked, future calls to getNotificationTraySeen() will return the new isSeen value. It is recommended to call this method as soon as the tray UI is opened.
This method updates the global tray seen state, not individual notification items. Use markSeen() on individual items for fine-grained tracking.
import AmitySDKclass NotificationTrayViewController: UIViewController { private let repository = AmityNotificationTrayRepository() override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // Mark tray as seen when user opens it markTrayAsSeen() } private func markTrayAsSeen() { repository.markNotificationTraySeen { [weak self] result in DispatchQueue.main.async { switch result { case .success: self?.updateGlobalBadgeState() case .failure(let error): print("Failed to mark tray as seen: \(error)") } } } } private func updateGlobalBadgeState() { // Update global app badge NotificationCenter.default.post( name: .notificationTrayMarkedAsSeen, object: nil ) }}
Copy
Ask AI
import com.amity.socialcloud.sdk.AmityCoreClientclass NotificationTrayActivity : AppCompatActivity() { private lateinit var repository: AmityNotificationTrayRepository override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) repository = AmityCoreClient.newNotificationRepository() } override fun onResume() { super.onResume() // Mark tray as seen when user opens it markTrayAsSeen() } private fun markTrayAsSeen() { repository.markNotificationTraySeen() .observeOn(AndroidSchedulers.mainThread()) .subscribe({ updateGlobalBadgeState() }, { error -> Log.e("NotificationTray", "Failed to mark tray as seen", error) }) } private fun updateGlobalBadgeState() { // Update global app badge val intent = Intent(ACTION_NOTIFICATION_TRAY_MARKED_SEEN) LocalBroadcastManager.getInstance(this).sendBroadcast(intent) } companion object { const val ACTION_NOTIFICATION_TRAY_MARKED_SEEN = "com.app.notification_tray_marked_seen" }}
Copy
Ask AI
import { AmityNotificationTrayRepository } from '@amityco/ts-sdk';class NotificationTrayManager { private repository: AmityNotificationTrayRepository; constructor() { this.repository = new AmityNotificationTrayRepository(); } async onTrayOpened(): Promise<void> { try { // Mark tray as seen when user opens it await this.markTrayAsSeen(); } catch (error) { console.error('Failed to mark tray as seen:', error); } } private async markTrayAsSeen(): Promise<void> { await this.repository.markNotificationTraySeen(); this.updateGlobalBadgeState(); } private updateGlobalBadgeState(): void { // Emit custom event for global badge updates const event = new CustomEvent('notificationTrayMarkedSeen'); window.dispatchEvent(event); }}
Copy
Ask AI
import 'package:amity_sdk/amity_sdk.dart';class NotificationTrayScreen extends StatefulWidget { @override _NotificationTrayScreenState createState() => _NotificationTrayScreenState();}class _NotificationTrayScreenState extends State<NotificationTrayScreen> { late AmityNotificationTrayRepository _repository; @override void initState() { super.initState(); _repository = AmityNotificationTrayRepository(); // Mark tray as seen when screen is opened WidgetsBinding.instance.addPostFrameCallback((_) { _markTrayAsSeen(); }); } Future<void> _markTrayAsSeen() async { try { await _repository.markNotificationTraySeen(); _updateGlobalBadgeState(); } catch (error) { print('Failed to mark tray as seen: $error'); } } void _updateGlobalBadgeState() { // Notify other parts of the app NotificationBadgeManager.instance.refreshBadgeState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Notifications')), body: NotificationTrayList(), ); }}
// Option 1: Mark when view appears (recommended)override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) markTrayAsSeen()}// Option 2: Mark with slight delay for better UXoverride func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.markTrayAsSeen() }}// Option 3: Mark when user scrolls (indicating engagement)func scrollViewDidScroll(_ scrollView: UIScrollView) { if !hasMarkedAsSeen && scrollView.contentOffset.y > 50 { hasMarkedAsSeen = true markTrayAsSeen() }}
Copy
Ask AI
// Option 1: Mark when activity resumes (recommended)override fun onResume() { super.onResume() markTrayAsSeen()}// Option 2: Mark with delay for better UXoverride fun onResume() { super.onResume() Handler(Looper.getMainLooper()).postDelayed({ markTrayAsSeen() }, 500)}// Option 3: Mark when RecyclerView is scrolledprivate val scrollListener = object : RecyclerView.OnScrollListener() { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { if (!hasMarkedAsSeen && dy > 0) { hasMarkedAsSeen = true markTrayAsSeen() } }}
Copy
Ask AI
// Option 1: Mark when component mounts (recommended)useEffect(() => { markTrayAsSeen();}, []);// Option 2: Mark with delay for better UXuseEffect(() => { const timer = setTimeout(() => { markTrayAsSeen(); }, 500); return () => clearTimeout(timer);}, []);// Option 3: Mark when user scrollsuseEffect(() => { const handleScroll = () => { if (!hasMarkedAsSeen && window.scrollY > 50) { setHasMarkedAsSeen(true); markTrayAsSeen(); } }; window.addEventListener('scroll', handleScroll); return () => window.removeEventListener('scroll', handleScroll);}, [hasMarkedAsSeen]);