11import 'dart:async' ;
2+ import 'dart:convert' ;
23import 'package:app_links/app_links.dart' ;
34import 'package:flutter/material.dart' ;
5+ import 'package:latlong2/latlong.dart' ;
46
57import '../models/node_profile.dart' ;
68import '../models/operator_profile.dart' ;
9+ import '../models/osm_node.dart' ;
10+ import 'http_client.dart' ;
711import 'profile_import_service.dart' ;
812import 'operator_profile_import_service.dart' ;
913import '../screens/profile_editor.dart' ;
@@ -16,6 +20,9 @@ class DeepLinkService {
1620
1721 late AppLinks _appLinks;
1822 StreamSubscription <Uri >? _linkSubscription;
23+
24+ /// Callback for HomeScreen to receive node deep links
25+ void Function (OsmNode node)? onNodeDeepLink;
1926
2027 /// Initialize deep link handling (sets up stream listener only)
2128 Future <void > init () async {
@@ -45,6 +52,9 @@ class DeepLinkService {
4552 case 'profiles' :
4653 _handleProfilesLink (uri);
4754 break ;
55+ case 'node' :
56+ _handleNodeLink (uri);
57+ break ;
4858 case 'auth' :
4959 // OAuth links are handled by flutter_web_auth_2
5060 debugPrint ('[DeepLinkService] OAuth link handled by flutter_web_auth_2' );
@@ -71,6 +81,59 @@ class DeepLinkService {
7181 }
7282 }
7383
84+ /// Handle node deep link: `deflockapp://node?id=<nodeId>`
85+ Future <void > _handleNodeLink (Uri uri) async {
86+ final idStr = uri.queryParameters['id' ];
87+ final nodeId = int .tryParse (idStr ?? '' );
88+ if (nodeId == null ) {
89+ _showError ('Invalid node link: missing or invalid ID' );
90+ return ;
91+ }
92+
93+ final node = await _fetchNodeById (nodeId);
94+ if (node == null ) {
95+ _showError ('Node $nodeId not found' );
96+ return ;
97+ }
98+
99+ if (onNodeDeepLink != null ) {
100+ onNodeDeepLink !(node);
101+ } else {
102+ debugPrint ('[DeepLinkService] No node deep link handler registered' );
103+ }
104+ }
105+
106+ /// Fetch an OSM node by ID from the OpenStreetMap API
107+ Future <OsmNode ?> _fetchNodeById (int nodeId) async {
108+ try {
109+ final url = Uri .parse ('https://api.openstreetmap.org/api/0.6/node/$nodeId .json' );
110+ final client = UserAgentClient ();
111+ final response = await client.get (url);
112+ if (response.statusCode != 200 ) return null ;
113+
114+ final json = jsonDecode (response.body);
115+ final elements = json['elements' ] as List ? ;
116+ if (elements == null || elements.isEmpty) return null ;
117+
118+ final e = elements[0 ];
119+ final tags = < String , String > {};
120+ if (e['tags' ] != null ) {
121+ (e['tags' ] as Map <String , dynamic >).forEach ((k, v) {
122+ tags[k] = v.toString ();
123+ });
124+ }
125+
126+ return OsmNode (
127+ id: e['id' ] as int ,
128+ coord: LatLng ((e['lat' ] as num ).toDouble (), (e['lon' ] as num ).toDouble ()),
129+ tags: tags,
130+ );
131+ } catch (e) {
132+ debugPrint ('[DeepLinkService] Failed to fetch node $nodeId : $e ' );
133+ return null ;
134+ }
135+ }
136+
74137 /// Handle profile-related deep links
75138 void _handleProfilesLink (Uri uri) {
76139 final segments = uri.pathSegments;
0 commit comments