added collections page

This commit is contained in:
2025-11-02 16:14:10 +01:00
parent 2d93d1a9d7
commit 6fb873163b
4 changed files with 271 additions and 1 deletions

View File

@@ -0,0 +1,79 @@
// service/maps_launcher_service.dart
import 'dart:io' show Platform;
import 'package:android_intent_plus/android_intent.dart';
class MapsLauncherService {
/// Opens a URL in Google Maps app
/// Falls back to browser if Maps app is not installed
static Future<bool> openInGoogleMaps(String url) async {
if (!Platform.isAndroid) {
// Handle iOS or other platforms if needed
return false;
}
try {
// Try to open in Google Maps app
final intent = AndroidIntent(
action: 'action_view',
data: url,
package: 'com.google.android.apps.maps',
);
await intent.launch();
return true;
} catch (e) {
// Google Maps not installed, try browser as fallback
try {
final browserIntent = AndroidIntent(action: 'action_view', data: url);
await browserIntent.launch();
return true;
} catch (e) {
print('Failed to open maps link: $e');
return false;
}
}
}
/// Opens navigation to specific coordinates
static Future<bool> navigateToCoordinates(
String latitude,
String longitude,
) async {
final url = 'google.navigation:q=$latitude,$longitude';
return openInGoogleMaps(url);
}
/// Opens a search query in Google Maps
static Future<bool> searchInMaps(String query) async {
final encodedQuery = Uri.encodeComponent(query);
final url = 'geo:0,0?q=$encodedQuery';
return openInGoogleMaps(url);
}
/// Shares a Google Maps link or location via Android share sheet
static Future<bool> shareLocation({
required String text,
String? subject,
}) async {
if (!Platform.isAndroid) {
return false;
}
try {
final intent = AndroidIntent(
action: 'action_send',
type: 'text/plain',
arguments: {
'android.intent.extra.TEXT': text,
if (subject != null) 'android.intent.extra.SUBJECT': subject,
},
);
await intent.launch();
return true;
} catch (e) {
print('Failed to share location: $e');
return false;
}
}
}

View File

@@ -0,0 +1,116 @@
import 'package:flutter/services.dart';
class ShareIntentService {
static const _platform = MethodChannel('app.channel.shared.data');
static ShareIntentService? _instance;
// Singleton pattern
factory ShareIntentService() {
_instance ??= ShareIntentService._internal();
return _instance!;
}
ShareIntentService._internal();
/// Retrieves shared text from the platform channel
/// Returns null if no shared text is available
Future<String?> getSharedText() async {
try {
final String? sharedText = await _platform.invokeMethod('getSharedText');
return sharedText;
} on PlatformException catch (e) {
// Log error in production app
print('Failed to get shared text: ${e.message}');
return null;
}
}
/// Checks if the text is a Google Maps link
bool isGoogleMapsLink(String text) {
return text.contains('maps.google.com') ||
text.contains('maps.app.goo.gl') ||
text.contains('goo.gl/maps');
}
/// Extracts metadata from a Google Maps link
MapsLinkMetadata extractMetadata(String mapsLink) {
String? placeName;
String? latitude;
String? longitude;
String? address;
// Extract place name from URL
final placeMatch = RegExp(r'/place/([^/]+)').firstMatch(mapsLink);
if (placeMatch != null) {
placeName = Uri.decodeComponent(
placeMatch.group(1)!,
).replaceAll('+', ' ');
}
// Extract coordinates
final coordMatch = RegExp(
r'@(-?\d+\.\d+),(-?\d+\.\d+)',
).firstMatch(mapsLink);
if (coordMatch != null) {
latitude = coordMatch.group(1);
longitude = coordMatch.group(2);
}
// Extract search query/address
final searchMatch = RegExp(r'/search/([^/?]+)').firstMatch(mapsLink);
if (searchMatch != null) {
address = Uri.decodeComponent(searchMatch.group(1)!).replaceAll('+', ' ');
// Use address as place name if name not found
placeName ??= address;
}
// Extract from data parameter (alternative format)
final dataMatch = RegExp(r'[?&]q=([^&]+)').firstMatch(mapsLink);
if (dataMatch != null && placeName == null) {
final query = Uri.decodeComponent(dataMatch.group(1)!);
// Check if it's coordinates
final coordPattern = RegExp(r'^(-?\d+\.\d+),(-?\d+\.\d+)$');
final coords = coordPattern.firstMatch(query);
if (coords != null) {
latitude ??= coords.group(1);
longitude ??= coords.group(2);
} else {
placeName = query.replaceAll('+', ' ');
}
}
return MapsLinkMetadata(
url: mapsLink,
placeName: placeName ?? 'Unknown Location',
latitude: latitude,
longitude: longitude,
address: address,
);
}
}
/// Data class for Google Maps link metadata
class MapsLinkMetadata {
final String url;
final String placeName;
final String? latitude;
final String? longitude;
final String? address;
const MapsLinkMetadata({
required this.url,
required this.placeName,
this.latitude,
this.longitude,
this.address,
});
String get coordinates {
if (latitude != null && longitude != null) {
return '$latitude, $longitude';
}
return '';
}
bool get hasCoordinates => latitude != null && longitude != null;
}