···103103 if (reason == 'follow' && author != null) {
104104 // Navigate to profile for follow notifications
105105 router.push(ProfileRoute(did: author));
106106+ } else if (reason == 'reply' && recordUri != null) {
107107+ router.push(StandalonePostRoute(postUri: recordUri));
106108 } else if (reasonSubject != null) {
107109 // For likes/reposts, navigate to the subject (the post being liked/reposted)
108110 router.push(StandalonePostRoute(postUri: reasonSubject));
109111 } else if (recordUri != null) {
110110- // For replies/mentions, navigate to the record itself
112112+ // For mentions and other record notifications, navigate to the record itself
111113 router.push(StandalonePostRoute(postUri: recordUri));
112114 } else if (author != null) {
113115 // Fallback to author profile
···11import 'dart:async';
2233-import 'package:atproto_core/atproto_core.dart';
43import 'package:auto_route/auto_route.dart';
54import 'package:flutter/material.dart';
65import 'package:flutter_riverpod/flutter_riverpod.dart';
77-import 'package:get_it/get_it.dart';
86import 'package:spark/src/core/design_system/components/atoms/icons.dart';
97import 'package:spark/src/core/network/atproto/data/models/notification_models.dart'
108 as models;
1111-import 'package:spark/src/core/network/atproto/data/models/record_models.dart'
1212- hide Image;
1313-import 'package:spark/src/core/network/atproto/data/repositories/sprk_repository.dart';
149import 'package:spark/src/core/routing/app_router.dart';
1510import 'package:spark/src/core/ui/foundation/colors.dart';
1611import 'package:spark/src/core/ui/widgets/user_avatar.dart';
···3631class _NotificationItemState extends ConsumerState<NotificationItem> {
3732 bool _hasBeenViewed = false;
3833 Timer? _viewTimer;
3939-4040- SprkRepository get _sprkRepository => GetIt.instance<SprkRepository>();
41344235 /// The primary notification (most recent in the group)
4336 models.Notification get notification =>
···182175 // Navigate to profile (use first author for grouped follows)
183176 context.router.push(ProfileRoute(did: notification.author.did));
184177 } else if (notification.reason == 'reply') {
185185- // Reply notification - navigate to root post with reply highlighted
186178 final replyUri = notification.uri.toString();
187187- final rootPostUri = _getRootPostUri();
188188- if (rootPostUri != null) {
189189- context.router.push(
190190- StandalonePostRoute(
191191- postUri: rootPostUri,
192192- highlightedReplyUri: replyUri,
193193- ),
194194- );
195195- } else {
196196- // Fallback to standalone post
197197- context.router.push(StandalonePostRoute(postUri: replyUri));
198198- }
199199- } else if (notification.reason == 'like' && _isReplySubject()) {
200200- // Like on a reply - get root post URI from embedded subject or fetch it
201201- final replyUri = notification.reasonSubject!.toString();
202202-203203- // First try to get root from embedded subject record
204204- var rootPostUri = _getRootPostUriFromEmbeddedSubject();
205205-206206- // If not available, fetch the reply record
207207- rootPostUri ??= await _fetchRootPostUriFromReply(replyUri);
208208-209209- if (rootPostUri != null && context.mounted) {
210210- context.router.push(
211211- StandalonePostRoute(
212212- postUri: rootPostUri,
213213- highlightedReplyUri: replyUri,
214214- ),
215215- );
216216- } else if (context.mounted) {
217217- // Fallback to standalone post showing the reply
218218- context.router.push(StandalonePostRoute(postUri: replyUri));
219219- }
179179+ context.router.push(StandalonePostRoute(postUri: replyUri));
220180 } else if (notification.reasonSubject != null) {
221181 // Navigate to the post/thread
222182 final reasonSubjectStr = notification.reasonSubject!.toString();
···233193 // Fallback to author profile
234194 context.router.push(ProfileRoute(did: notification.author.did));
235195 }
236236- }
237237-238238- /// Check if the reasonSubject is a reply (not a post)
239239- bool _isReplySubject() {
240240- if (notification.reasonSubject == null) return false;
241241- final collection = notification.reasonSubject!.collection.toString();
242242- return collection.contains('reply');
243243- }
244244-245245- /// Get the root post URI from a reply notification's record
246246- String? _getRootPostUri() {
247247- try {
248248- final record = notification.record;
249249- final reply = record['reply'] as Map<String, dynamic>?;
250250- if (reply != null) {
251251- final root = reply['root'] as Map<String, dynamic>?;
252252- if (root != null) {
253253- return root['uri'] as String?;
254254- }
255255- }
256256- } catch (e) {
257257- // Ignore parsing errors
258258- }
259259- return null;
260260- }
261261-262262- /// Get the root post URI from the embedded subject record (for like/repost on reply)
263263- String? _getRootPostUriFromEmbeddedSubject() {
264264- try {
265265- final record = notification.record;
266266- // The backend embeds the subject record in notification.record['subject']
267267- final subject = record['subject'] as Map<String, dynamic>?;
268268- if (subject != null) {
269269- final reply = subject['reply'] as Map<String, dynamic>?;
270270- if (reply != null) {
271271- final root = reply['root'] as Map<String, dynamic>?;
272272- if (root != null) {
273273- return root['uri'] as String?;
274274- }
275275- }
276276- }
277277- } catch (e) {
278278- // Ignore parsing errors
279279- }
280280- return null;
281281- }
282282-283283- /// Fetch the reply record and extract the root post URI
284284- Future<String?> _fetchRootPostUriFromReply(String replyUriStr) async {
285285- try {
286286- final replyUri = AtUri.parse(replyUriStr);
287287- final result = await _sprkRepository.repo.getRecord(uri: replyUri);
288288- final record = result.record;
289289-290290- // Check if it's a reply record and extract the root URI
291291- if (record is ReplyRecord) {
292292- return record.reply.root.uri.toString();
293293- } else if (record is BskyPostRecord && record.reply != null) {
294294- return record.reply!.root.uri.toString();
295295- }
296296- } catch (e) {
297297- // If we can't fetch the record, return null to use fallback
298298- }
299299- return null;
300196 }
301197302198 String? _getContentPreview() {