mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-08-14 23:20:46 +02:00
Merge pull request #28 from heathdutton/issue-27-search-viewbox
Pass (rough) viewbox to search for location-biased results
This commit is contained in:
@@ -1,4 +1,9 @@
|
|||||||
{
|
{
|
||||||
|
"2.4.4": {
|
||||||
|
"content": [
|
||||||
|
"• Search results now prioritize locations near your current map view"
|
||||||
|
]
|
||||||
|
},
|
||||||
"2.4.3": {
|
"2.4.3": {
|
||||||
"content": [
|
"content": [
|
||||||
"• Fixed 360° FOV rendering - devices with full circle coverage now render as complete rings instead of having a wedge cut out or being a line",
|
"• Fixed 360° FOV rendering - devices with full circle coverage now render as complete rings instead of having a wedge cut out or being a line",
|
||||||
|
|||||||
+3
-2
@@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter_map/flutter_map.dart' show LatLngBounds;
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:latlong2/latlong.dart';
|
import 'package:latlong2/latlong.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
@@ -569,8 +570,8 @@ class AppState extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ---------- Navigation Methods - Simplified ----------
|
// ---------- Navigation Methods - Simplified ----------
|
||||||
void enterSearchMode(LatLng mapCenter) {
|
void enterSearchMode(LatLng mapCenter, {LatLngBounds? viewbox}) {
|
||||||
_navigationState.enterSearchMode(mapCenter);
|
_navigationState.enterSearchMode(mapCenter, viewbox: viewbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cancelNavigation() {
|
void cancelNavigation() {
|
||||||
|
|||||||
@@ -138,7 +138,8 @@ class NavigationCoordinator {
|
|||||||
// Enter search mode
|
// Enter search mode
|
||||||
try {
|
try {
|
||||||
final center = mapController.mapController.camera.center;
|
final center = mapController.mapController.camera.center;
|
||||||
appState.enterSearchMode(center);
|
final viewbox = mapController.mapController.camera.visibleBounds;
|
||||||
|
appState.enterSearchMode(center, viewbox: viewbox);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('[NavigationCoordinator] Could not get map center for search: $e');
|
debugPrint('[NavigationCoordinator] Could not get map center for search: $e');
|
||||||
// Fallback to default location
|
// Fallback to default location
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter_map/flutter_map.dart' show LatLngBounds;
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:latlong2/latlong.dart';
|
import 'package:latlong2/latlong.dart';
|
||||||
|
|
||||||
@@ -12,19 +13,19 @@ class SearchService {
|
|||||||
static const Duration _timeout = Duration(seconds: 10);
|
static const Duration _timeout = Duration(seconds: 10);
|
||||||
|
|
||||||
/// Search for places using Nominatim geocoding service
|
/// Search for places using Nominatim geocoding service
|
||||||
Future<List<SearchResult>> search(String query) async {
|
Future<List<SearchResult>> search(String query, {LatLngBounds? viewbox}) async {
|
||||||
if (query.trim().isEmpty) {
|
if (query.trim().isEmpty) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if query looks like coordinates first
|
// Check if query looks like coordinates first
|
||||||
final coordResult = _tryParseCoordinates(query.trim());
|
final coordResult = _tryParseCoordinates(query.trim());
|
||||||
if (coordResult != null) {
|
if (coordResult != null) {
|
||||||
return [coordResult];
|
return [coordResult];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, use Nominatim API
|
// Otherwise, use Nominatim API
|
||||||
return await _searchNominatim(query.trim());
|
return await _searchNominatim(query.trim(), viewbox: viewbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to parse various coordinate formats
|
/// Try to parse various coordinate formats
|
||||||
@@ -52,14 +53,37 @@ class SearchService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Search using Nominatim API
|
/// Search using Nominatim API
|
||||||
Future<List<SearchResult>> _searchNominatim(String query) async {
|
Future<List<SearchResult>> _searchNominatim(String query, {LatLngBounds? viewbox}) async {
|
||||||
final uri = Uri.parse('$_baseUrl/search').replace(queryParameters: {
|
final params = {
|
||||||
'q': query,
|
'q': query,
|
||||||
'format': 'json',
|
'format': 'json',
|
||||||
'limit': _maxResults.toString(),
|
'limit': _maxResults.toString(),
|
||||||
'addressdetails': '1',
|
'addressdetails': '1',
|
||||||
'extratags': '1',
|
'extratags': '1',
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (viewbox != null) {
|
||||||
|
double round1(double v) => (v * 10).round() / 10;
|
||||||
|
var west = round1(viewbox.west);
|
||||||
|
var east = round1(viewbox.east);
|
||||||
|
var south = round1(viewbox.south);
|
||||||
|
var north = round1(viewbox.north);
|
||||||
|
|
||||||
|
if (east - west < 0.5) {
|
||||||
|
final mid = (east + west) / 2;
|
||||||
|
west = mid - 0.25;
|
||||||
|
east = mid + 0.25;
|
||||||
|
}
|
||||||
|
if (north - south < 0.5) {
|
||||||
|
final mid = (north + south) / 2;
|
||||||
|
south = mid - 0.25;
|
||||||
|
north = mid + 0.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
params['viewbox'] = '$west,$north,$east,$south';
|
||||||
|
}
|
||||||
|
|
||||||
|
final uri = Uri.parse('$_baseUrl/search').replace(queryParameters: params);
|
||||||
|
|
||||||
debugPrint('[SearchService] Searching Nominatim: $uri');
|
debugPrint('[SearchService] Searching Nominatim: $uri');
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_map/flutter_map.dart' show LatLngBounds;
|
||||||
import 'package:latlong2/latlong.dart';
|
import 'package:latlong2/latlong.dart';
|
||||||
|
|
||||||
import '../models/search_result.dart';
|
import '../models/search_result.dart';
|
||||||
@@ -31,7 +32,8 @@ class NavigationState extends ChangeNotifier {
|
|||||||
bool _isSearchLoading = false;
|
bool _isSearchLoading = false;
|
||||||
List<SearchResult> _searchResults = [];
|
List<SearchResult> _searchResults = [];
|
||||||
String _lastQuery = '';
|
String _lastQuery = '';
|
||||||
|
LatLngBounds? _searchViewbox;
|
||||||
|
|
||||||
// Location state
|
// Location state
|
||||||
LatLng? _provisionalPinLocation;
|
LatLng? _provisionalPinLocation;
|
||||||
String? _provisionalPinAddress;
|
String? _provisionalPinAddress;
|
||||||
@@ -106,19 +108,20 @@ class NavigationState extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// BRUTALIST: Single entry point to search mode
|
/// BRUTALIST: Single entry point to search mode
|
||||||
void enterSearchMode(LatLng mapCenter) {
|
void enterSearchMode(LatLng mapCenter, {LatLngBounds? viewbox}) {
|
||||||
debugPrint('[NavigationState] enterSearchMode - current mode: $_mode');
|
debugPrint('[NavigationState] enterSearchMode - current mode: $_mode');
|
||||||
|
|
||||||
if (_mode != AppNavigationMode.normal) {
|
if (_mode != AppNavigationMode.normal) {
|
||||||
debugPrint('[NavigationState] Cannot enter search mode - not in normal mode');
|
debugPrint('[NavigationState] Cannot enter search mode - not in normal mode');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_mode = AppNavigationMode.search;
|
_mode = AppNavigationMode.search;
|
||||||
_provisionalPinLocation = mapCenter;
|
_provisionalPinLocation = mapCenter;
|
||||||
_provisionalPinAddress = null;
|
_provisionalPinAddress = null;
|
||||||
|
_searchViewbox = viewbox;
|
||||||
_clearSearchResults();
|
_clearSearchResults();
|
||||||
|
|
||||||
debugPrint('[NavigationState] Entered search mode');
|
debugPrint('[NavigationState] Entered search mode');
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
@@ -149,7 +152,8 @@ class NavigationState extends ChangeNotifier {
|
|||||||
_showingOverview = false;
|
_showingOverview = false;
|
||||||
_nextPointIsStart = false;
|
_nextPointIsStart = false;
|
||||||
_routingError = null;
|
_routingError = null;
|
||||||
|
_searchViewbox = null;
|
||||||
|
|
||||||
// Clear search
|
// Clear search
|
||||||
_clearSearchResults();
|
_clearSearchResults();
|
||||||
|
|
||||||
@@ -336,21 +340,21 @@ class NavigationState extends ChangeNotifier {
|
|||||||
_clearSearchResults();
|
_clearSearchResults();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.trim() == _lastQuery.trim()) return;
|
if (query.trim() == _lastQuery.trim()) return;
|
||||||
|
|
||||||
_setSearchLoading(true);
|
_setSearchLoading(true);
|
||||||
_lastQuery = query.trim();
|
_lastQuery = query.trim();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final results = await _searchService.search(query.trim());
|
final results = await _searchService.search(query.trim(), viewbox: _searchViewbox);
|
||||||
_searchResults = results;
|
_searchResults = results;
|
||||||
debugPrint('[NavigationState] Found ${results.length} results');
|
debugPrint('[NavigationState] Found ${results.length} results');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('[NavigationState] Search failed: $e');
|
debugPrint('[NavigationState] Search failed: $e');
|
||||||
_searchResults = [];
|
_searchResults = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
_setSearchLoading(false);
|
_setSearchLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
name: deflockapp
|
name: deflockapp
|
||||||
description: Map public surveillance infrastructure with OpenStreetMap
|
description: Map public surveillance infrastructure with OpenStreetMap
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
version: 2.4.3+41 # The thing after the + is the version code, incremented with each release
|
version: 2.4.4+42 # The thing after the + is the version code, incremented with each release
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.5.0 <4.0.0" # oauth2_client 4.x needs Dart 3.5+
|
sdk: ">=3.5.0 <4.0.0" # oauth2_client 4.x needs Dart 3.5+
|
||||||
|
|||||||
Reference in New Issue
Block a user