mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-02-02 06:46:22 +01:00
Add OSM as alternative map provider
This commit is contained in:
parent
d57be5e77a
commit
a63d3e43a1
15 changed files with 290 additions and 38 deletions
BIN
assets/2.0x/gps_map_pin.png
Normal file
BIN
assets/2.0x/gps_map_pin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
BIN
assets/3.0x/gps_map_pin.png
Normal file
BIN
assets/3.0x/gps_map_pin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5 KiB |
BIN
assets/gps_map_pin.png
Normal file
BIN
assets/gps_map_pin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
|
@ -352,6 +352,7 @@
|
|||
"settingsScreenBrightnessDescription": "Override system brightness level",
|
||||
"settingsForceRotationTitle": "Ignore rotation lock",
|
||||
"settingsForceRotationDescription": "Rotate the screen even when auto rotation is disabled",
|
||||
"settingsMapProviderTitle": "Map provider",
|
||||
"settingsAlbumTitle": "Album",
|
||||
"settingsAlbumDescription": "Customize albums",
|
||||
"settingsAlbumPageTitle": "Album settings",
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"settingsShareFolderDialogDescription",
|
||||
"settingsShareFolderPickerDescription",
|
||||
"settingsServerAppSectionTitle",
|
||||
"settingsMapProviderTitle",
|
||||
"settingsAlbumTitle",
|
||||
"settingsAlbumDescription",
|
||||
"settingsAlbumPageTitle",
|
||||
|
@ -59,6 +60,7 @@
|
|||
"settingsShareFolderDialogDescription",
|
||||
"settingsShareFolderPickerDescription",
|
||||
"settingsServerAppSectionTitle",
|
||||
"settingsMapProviderTitle",
|
||||
"settingsAlbumTitle",
|
||||
"settingsAlbumDescription",
|
||||
"settingsAlbumPageTitle",
|
||||
|
@ -132,6 +134,7 @@
|
|||
"settingsScreenBrightnessDescription",
|
||||
"settingsForceRotationTitle",
|
||||
"settingsForceRotationDescription",
|
||||
"settingsMapProviderTitle",
|
||||
"settingsAlbumTitle",
|
||||
"settingsAlbumDescription",
|
||||
"settingsAlbumPageTitle",
|
||||
|
@ -235,6 +238,10 @@
|
|||
"defaultButtonLabel"
|
||||
],
|
||||
|
||||
"es": [
|
||||
"settingsMapProviderTitle"
|
||||
],
|
||||
|
||||
"fr": [
|
||||
"collectionsTooltip",
|
||||
"settingsAccountTitle",
|
||||
|
@ -252,6 +259,7 @@
|
|||
"settingsScreenBrightnessDescription",
|
||||
"settingsForceRotationTitle",
|
||||
"settingsForceRotationDescription",
|
||||
"settingsMapProviderTitle",
|
||||
"settingsAlbumTitle",
|
||||
"settingsAlbumDescription",
|
||||
"settingsAlbumPageTitle",
|
||||
|
@ -344,6 +352,7 @@
|
|||
"settingsShareFolderDialogDescription",
|
||||
"settingsShareFolderPickerDescription",
|
||||
"settingsServerAppSectionTitle",
|
||||
"settingsMapProviderTitle",
|
||||
"settingsAlbumTitle",
|
||||
"settingsAlbumDescription",
|
||||
"settingsAlbumPageTitle",
|
||||
|
|
|
@ -2,8 +2,8 @@ import 'package:flutter/widgets.dart';
|
|||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class GpsMap extends StatelessWidget {
|
||||
const GpsMap({
|
||||
class GoogleGpsMap extends StatelessWidget {
|
||||
const GoogleGpsMap({
|
||||
Key? key,
|
||||
required this.center,
|
||||
required this.zoom,
|
||||
|
@ -41,7 +41,6 @@ class GpsMap extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
/// A pair of latitude and longitude coordinates, stored as degrees
|
||||
final Tuple2<double, double> center;
|
||||
final double zoom;
|
||||
final VoidCallback? onTap;
|
|
@ -1,5 +1,5 @@
|
|||
export 'db_util.dart';
|
||||
export 'download.dart';
|
||||
export 'file_saver.dart';
|
||||
export 'gps_map.dart';
|
||||
export 'google_gps_map.dart';
|
||||
export 'universal_storage.dart';
|
||||
|
|
|
@ -133,6 +133,11 @@ class Pref {
|
|||
Future<bool> setNewSharedAlbum(bool value) =>
|
||||
provider.setBool(PrefKey.newSharedAlbum, value);
|
||||
|
||||
int? getGpsMapProvider() => provider.getInt(PrefKey.gpsMapProvider);
|
||||
int getGpsMapProviderOr(int def) => getGpsMapProvider() ?? def;
|
||||
Future<bool> setGpsMapProvider(int value) =>
|
||||
provider.setInt(PrefKey.gpsMapProvider, value);
|
||||
|
||||
bool? isLabEnableSharedAlbum() =>
|
||||
provider.getBool(PrefKey.labEnableSharedAlbum);
|
||||
bool isLabEnableSharedAlbumOr(bool def) => isLabEnableSharedAlbum() ?? def;
|
||||
|
@ -308,6 +313,7 @@ enum PrefKey {
|
|||
isSlideshowShuffle,
|
||||
isSlideshowRepeat,
|
||||
isAlbumBrowserShowDate,
|
||||
gpsMapProvider,
|
||||
}
|
||||
|
||||
extension on PrefKey {
|
||||
|
@ -353,6 +359,8 @@ extension on PrefKey {
|
|||
return "isSlideshowRepeat";
|
||||
case PrefKey.isAlbumBrowserShowDate:
|
||||
return "isAlbumBrowserShowDate";
|
||||
case PrefKey.gpsMapProvider:
|
||||
return "gpsMapProvider";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ import 'package:/nc_photos/mobile/ui_hack.dart' if (dart.library.html) 'dart:ui'
|
|||
import 'package:flutter/widgets.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class GpsMap extends StatefulWidget {
|
||||
const GpsMap({
|
||||
class GoogleGpsMap extends StatefulWidget {
|
||||
const GoogleGpsMap({
|
||||
Key? key,
|
||||
required this.center,
|
||||
required this.zoom,
|
||||
|
@ -15,15 +15,14 @@ class GpsMap extends StatefulWidget {
|
|||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
createState() => _GpsMapState();
|
||||
createState() => _GoogleGpsMapState();
|
||||
|
||||
/// A pair of latitude and longitude coordinates, stored as degrees
|
||||
final Tuple2<double, double> center;
|
||||
final double zoom;
|
||||
final void Function()? onTap;
|
||||
}
|
||||
|
||||
class _GpsMapState extends State<GpsMap> {
|
||||
class _GoogleGpsMapState extends State<GoogleGpsMap> {
|
||||
@override
|
||||
initState() {
|
||||
super.initState();
|
||||
|
@ -45,5 +44,5 @@ class _GpsMapState extends State<GpsMap> {
|
|||
static const _apiKey = "";
|
||||
|
||||
String get viewType =>
|
||||
"mapIframe(${widget.center.item1},${widget.center.item2})";
|
||||
"googleMapIframe(${widget.center.item1},${widget.center.item2})";
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
export 'db_util.dart';
|
||||
export 'download.dart';
|
||||
export 'file_saver.dart';
|
||||
export 'gps_map.dart';
|
||||
export 'google_gps_map.dart';
|
||||
export 'universal_storage.dart';
|
||||
|
|
124
lib/widget/gps_map.dart
Normal file
124
lib/widget/gps_map.dart
Normal file
|
@ -0,0 +1,124 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:nc_photos/mobile/platform.dart'
|
||||
if (dart.library.html) 'package:nc_photos/web/platform.dart' as platform;
|
||||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
enum GpsMapProvider {
|
||||
// the order must not be changed
|
||||
google,
|
||||
osm,
|
||||
}
|
||||
|
||||
extension GpsMapProviderExtension on GpsMapProvider {
|
||||
String toUserString() {
|
||||
switch (this) {
|
||||
case GpsMapProvider.google:
|
||||
return "Google Maps";
|
||||
|
||||
case GpsMapProvider.osm:
|
||||
return "OpenStreetMap";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GpsMap extends StatelessWidget {
|
||||
const GpsMap({
|
||||
Key? key,
|
||||
required this.center,
|
||||
required this.zoom,
|
||||
this.onTap,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
if (GpsMapProvider.values[Pref().getGpsMapProviderOr(0)] ==
|
||||
GpsMapProvider.osm) {
|
||||
return _OsmGpsMap(
|
||||
center: center,
|
||||
zoom: zoom,
|
||||
onTap: onTap,
|
||||
);
|
||||
} else {
|
||||
return _GoogleGpsMap(
|
||||
center: center,
|
||||
zoom: zoom,
|
||||
onTap: onTap,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A pair of latitude and longitude coordinates, stored as degrees
|
||||
final Tuple2<double, double> center;
|
||||
final double zoom;
|
||||
final void Function()? onTap;
|
||||
}
|
||||
|
||||
typedef _GoogleGpsMap = platform.GoogleGpsMap;
|
||||
|
||||
class _OsmGpsMap extends StatelessWidget {
|
||||
const _OsmGpsMap({
|
||||
Key? key,
|
||||
required this.center,
|
||||
required this.zoom,
|
||||
this.onTap,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
const double pinSize = 48;
|
||||
final centerLl = LatLng(center.item1, center.item2);
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
launch(
|
||||
"https://www.openstreetmap.org/?mlat=${center.item1}&mlon=${center.item2}#map=${zoom.toInt()}/${center.item1}/${center.item2}");
|
||||
},
|
||||
behavior: HitTestBehavior.opaque,
|
||||
// IgnorePointer is needed to prevent FlutterMap absorbing all pointer
|
||||
// events
|
||||
child: IgnorePointer(
|
||||
child: FlutterMap(
|
||||
options: MapOptions(
|
||||
center: centerLl,
|
||||
zoom: zoom,
|
||||
allowPanning: false,
|
||||
enableScrollWheel: false,
|
||||
interactiveFlags: InteractiveFlag.none,
|
||||
),
|
||||
layers: [
|
||||
TileLayerOptions(
|
||||
urlTemplate: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
attributionBuilder: (_) {
|
||||
return const Text(
|
||||
"© OpenStreetMap contributors",
|
||||
style: TextStyle(color: Colors.black),
|
||||
);
|
||||
},
|
||||
),
|
||||
MarkerLayerOptions(
|
||||
markers: [
|
||||
Marker(
|
||||
width: pinSize,
|
||||
height: pinSize,
|
||||
point: centerLl,
|
||||
anchorPos: AnchorPos.align(AnchorAlign.top),
|
||||
builder: (context) => const Image(
|
||||
image: AssetImage("gps_map_pin.png"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final Tuple2<double, double> center;
|
||||
final double zoom;
|
||||
final void Function()? onTap;
|
||||
}
|
|
@ -17,6 +17,7 @@ import 'package:nc_photos/pref.dart';
|
|||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/widget/fancy_option_picker.dart';
|
||||
import 'package:nc_photos/widget/gps_map.dart';
|
||||
import 'package:nc_photos/widget/home.dart';
|
||||
import 'package:nc_photos/widget/root_picker.dart';
|
||||
import 'package:nc_photos/widget/share_folder_picker.dart';
|
||||
|
@ -105,17 +106,16 @@ class _SettingsState extends State<Settings> {
|
|||
label: L10n.global().settingsAccountTitle,
|
||||
builder: () => AccountSettingsWidget(account: widget.account),
|
||||
),
|
||||
if (platform_k.isMobile)
|
||||
_buildSubSettings(
|
||||
context,
|
||||
leading: Icon(
|
||||
Icons.view_carousel_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
label: L10n.global().settingsViewerTitle,
|
||||
description: L10n.global().settingsViewerDescription,
|
||||
builder: () => _ViewerSettings(),
|
||||
_buildSubSettings(
|
||||
context,
|
||||
leading: Icon(
|
||||
Icons.view_carousel_outlined,
|
||||
color: AppTheme.getUnfocusedIconColor(context),
|
||||
),
|
||||
label: L10n.global().settingsViewerTitle,
|
||||
description: L10n.global().settingsViewerDescription,
|
||||
builder: () => _ViewerSettings(),
|
||||
),
|
||||
_buildSubSettings(
|
||||
context,
|
||||
leading: Icon(
|
||||
|
@ -715,6 +715,7 @@ class _ViewerSettingsState extends State<_ViewerSettings> {
|
|||
super.initState();
|
||||
_screenBrightness = Pref().getViewerScreenBrightnessOr(-1);
|
||||
_isForceRotation = Pref().isViewerForceRotationOr(false);
|
||||
_gpsMapProvider = GpsMapProvider.values[Pref().getGpsMapProviderOr(0)];
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -738,19 +739,27 @@ class _ViewerSettingsState extends State<_ViewerSettings> {
|
|||
SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
SwitchListTile(
|
||||
title: Text(L10n.global().settingsScreenBrightnessTitle),
|
||||
subtitle:
|
||||
Text(L10n.global().settingsScreenBrightnessDescription),
|
||||
value: _screenBrightness >= 0,
|
||||
onChanged: (value) =>
|
||||
_onScreenBrightnessChanged(context, value),
|
||||
),
|
||||
SwitchListTile(
|
||||
title: Text(L10n.global().settingsForceRotationTitle),
|
||||
subtitle: Text(L10n.global().settingsForceRotationDescription),
|
||||
value: _isForceRotation,
|
||||
onChanged: (value) => _onForceRotationChanged(value),
|
||||
if (platform_k.isMobile)
|
||||
SwitchListTile(
|
||||
title: Text(L10n.global().settingsScreenBrightnessTitle),
|
||||
subtitle:
|
||||
Text(L10n.global().settingsScreenBrightnessDescription),
|
||||
value: _screenBrightness >= 0,
|
||||
onChanged: (value) =>
|
||||
_onScreenBrightnessChanged(context, value),
|
||||
),
|
||||
if (platform_k.isMobile)
|
||||
SwitchListTile(
|
||||
title: Text(L10n.global().settingsForceRotationTitle),
|
||||
subtitle:
|
||||
Text(L10n.global().settingsForceRotationDescription),
|
||||
value: _isForceRotation,
|
||||
onChanged: (value) => _onForceRotationChanged(value),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(L10n.global().settingsMapProviderTitle),
|
||||
subtitle: Text(_gpsMapProvider.toUserString()),
|
||||
onTap: () => _onMapProviderTap(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -789,7 +798,8 @@ class _ViewerSettingsState extends State<_ViewerSettings> {
|
|||
onChangeEnd: (value) async {
|
||||
brightness = value;
|
||||
try {
|
||||
await ScreenBrightness().setScreenBrightness(value);
|
||||
await ScreenBrightness()
|
||||
.setScreenBrightness(value);
|
||||
} catch (e, stackTrace) {
|
||||
_log.severe("Failed while setScreenBrightness", e,
|
||||
stackTrace);
|
||||
|
@ -830,6 +840,44 @@ class _ViewerSettingsState extends State<_ViewerSettings> {
|
|||
|
||||
void _onForceRotationChanged(bool value) => _setForceRotation(value);
|
||||
|
||||
Future<void> _onMapProviderTap(BuildContext context) async {
|
||||
final oldValue = _gpsMapProvider;
|
||||
final newValue = await showDialog<GpsMapProvider>(
|
||||
context: context,
|
||||
builder: (context) => FancyOptionPicker(
|
||||
items: GpsMapProvider.values
|
||||
.map((provider) => FancyOptionPickerItem(
|
||||
label: provider.toUserString(),
|
||||
isSelected: provider == oldValue,
|
||||
onSelect: () {
|
||||
_log.info(
|
||||
"[_onMapProviderTap] Set map provider: ${provider.toUserString()}");
|
||||
Navigator.of(context).pop(provider);
|
||||
},
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
if (newValue == null || newValue == oldValue) {
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
_gpsMapProvider = newValue;
|
||||
});
|
||||
try {
|
||||
await Pref().setGpsMapProvider(newValue.index);
|
||||
} catch (e, stackTrace) {
|
||||
_log.severe("[_onMapProviderTap] Failed writing pref", e, stackTrace);
|
||||
SnackBarManager().showSnackBar(SnackBar(
|
||||
content: Text(L10n.global().writePreferenceFailureNotification),
|
||||
duration: k.snackBarDurationNormal,
|
||||
));
|
||||
setState(() {
|
||||
_gpsMapProvider = oldValue;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _setScreenBrightness(int value) async {
|
||||
final oldValue = _screenBrightness;
|
||||
setState(() {
|
||||
|
@ -866,6 +914,7 @@ class _ViewerSettingsState extends State<_ViewerSettings> {
|
|||
|
||||
late int _screenBrightness;
|
||||
late bool _isForceRotation;
|
||||
late GpsMapProvider _gpsMapProvider;
|
||||
|
||||
static final _log = Logger("widget.settings._ViewerSettingsState");
|
||||
}
|
||||
|
|
|
@ -23,8 +23,6 @@ import 'package:nc_photos/entity/share/data_source.dart';
|
|||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||
import 'package:nc_photos/iterable_extension.dart';
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/mobile/platform.dart'
|
||||
if (dart.library.html) 'package:nc_photos/web/platform.dart' as platform;
|
||||
import 'package:nc_photos/notified_action.dart';
|
||||
import 'package:nc_photos/platform/features.dart' as features;
|
||||
import 'package:nc_photos/platform/k.dart' as platform_k;
|
||||
|
@ -36,6 +34,7 @@ import 'package:nc_photos/use_case/remove_from_album.dart';
|
|||
import 'package:nc_photos/use_case/update_album.dart';
|
||||
import 'package:nc_photos/use_case/update_property.dart';
|
||||
import 'package:nc_photos/widget/album_picker_dialog.dart';
|
||||
import 'package:nc_photos/widget/gps_map.dart';
|
||||
import 'package:nc_photos/widget/photo_date_time_edit_dialog.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
@ -248,7 +247,7 @@ class _ViewerDetailPaneState extends State<ViewerDetailPane> {
|
|||
if (features.isSupportMapView && _gps != null)
|
||||
SizedBox(
|
||||
height: 256,
|
||||
child: platform.GpsMap(
|
||||
child: GpsMap(
|
||||
center: _gps!,
|
||||
zoom: 16,
|
||||
onTap: _onMapTap,
|
||||
|
|
63
pubspec.lock
63
pubspec.lock
|
@ -309,6 +309,13 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_map:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_map
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.14.0"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -449,6 +456,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.1"
|
||||
latlong2:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: latlong2
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.8.1"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -456,6 +470,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
lists:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lists
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
logging:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -477,6 +498,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
mgrs_dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mgrs_dart
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -617,6 +645,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.0"
|
||||
positioned_tap_detector_2:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: positioned_tap_detector_2
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -624,6 +659,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
proj4dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: proj4dart
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -846,6 +888,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.0"
|
||||
transparent_image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: transparent_image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
tuple:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -860,6 +909,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
unicode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: unicode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.1"
|
||||
url_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1013,6 +1069,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.2.10"
|
||||
wkt_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wkt_parser
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
woozy_search:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -43,6 +43,7 @@ dependencies:
|
|||
url: https://gitlab.com/nkming2/exifdart.git
|
||||
ref: 1.1.0
|
||||
flutter_bloc: ^7.0.0
|
||||
flutter_map: ^0.14.0
|
||||
flutter_staggered_grid_view:
|
||||
git:
|
||||
url: https://gitlab.com/nkming2/flutter_staggered_grid_view
|
||||
|
|
Loading…
Reference in a new issue