mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-01-22 08:46:18 +01:00
Refactor: extract map
This commit is contained in:
parent
b4cd90d6d4
commit
436a760950
36 changed files with 529 additions and 276 deletions
|
@ -120,7 +120,6 @@ dependencies {
|
|||
implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))
|
||||
// fix crash on sdk33, need investigation
|
||||
implementation "androidx.window:window:1.0.0"
|
||||
implementation 'com.google.android.gms:play-services-maps:18.1.0'
|
||||
implementation 'com.nkming.nc_photos.np_android_core:np_android_core'
|
||||
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:2.0.3"
|
||||
}
|
||||
|
|
|
@ -4,10 +4,7 @@ import android.content.Intent
|
|||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.NonNull
|
||||
import com.google.android.gms.maps.MapsInitializer
|
||||
import com.google.android.gms.maps.OnMapsSdkInitializedCallback
|
||||
import com.nkming.nc_photos.np_android_core.UriUtil
|
||||
import com.nkming.nc_photos.np_android_core.logD
|
||||
import com.nkming.nc_photos.np_android_core.logE
|
||||
import com.nkming.nc_photos.np_android_core.logI
|
||||
import com.nkming.nc_photos.np_platform_image_processor.NpPlatformImageProcessorPlugin
|
||||
|
@ -18,8 +15,7 @@ import io.flutter.plugin.common.MethodCall
|
|||
import io.flutter.plugin.common.MethodChannel
|
||||
import java.net.URLEncoder
|
||||
|
||||
class MainActivity : FlutterActivity(), MethodChannel.MethodCallHandler,
|
||||
OnMapsSdkInitializedCallback {
|
||||
class MainActivity : FlutterActivity(), MethodChannel.MethodCallHandler {
|
||||
companion object {
|
||||
private const val METHOD_CHANNEL = "com.nkming.nc_photos/activity"
|
||||
|
||||
|
@ -33,9 +29,6 @@ class MainActivity : FlutterActivity(), MethodChannel.MethodCallHandler,
|
|||
logI(TAG, "Initial route: $route")
|
||||
_initialRoute = route
|
||||
}
|
||||
MapsInitializer.initialize(
|
||||
applicationContext, MapsInitializer.Renderer.LATEST, this
|
||||
)
|
||||
}
|
||||
|
||||
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
|
||||
|
@ -85,28 +78,10 @@ class MainActivity : FlutterActivity(), MethodChannel.MethodCallHandler,
|
|||
_initialRoute = null
|
||||
}
|
||||
|
||||
"isNewGMapsRenderer" -> {
|
||||
result.success(_isNewGMapsRenderer)
|
||||
}
|
||||
|
||||
else -> result.notImplemented()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMapsSdkInitialized(renderer: MapsInitializer.Renderer) {
|
||||
_isNewGMapsRenderer = when (renderer) {
|
||||
MapsInitializer.Renderer.LATEST -> {
|
||||
logD(TAG, "Using new map renderer")
|
||||
true
|
||||
}
|
||||
|
||||
MapsInitializer.Renderer.LEGACY -> {
|
||||
logD(TAG, "Using legacy map renderer")
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRouteFromImageProcessorResult(intent: Intent): String? {
|
||||
val resultUri = intent.getParcelableExtra<Uri>(
|
||||
NpPlatformImageProcessorPlugin.EXTRA_IMAGE_RESULT_URI
|
||||
|
@ -131,5 +106,4 @@ class MainActivity : FlutterActivity(), MethodChannel.MethodCallHandler,
|
|||
}
|
||||
|
||||
private var _initialRoute: String? = null
|
||||
private var _isNewGMapsRenderer = false
|
||||
}
|
||||
|
|
|
@ -37,13 +37,13 @@ import 'package:nc_photos/entity/tag/data_source.dart';
|
|||
import 'package:nc_photos/entity/tagged_file.dart';
|
||||
import 'package:nc_photos/entity/tagged_file/data_source.dart';
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/mobile/android/activity.dart';
|
||||
import 'package:nc_photos/mobile/android/android_info.dart';
|
||||
import 'package:nc_photos/mobile/platform.dart'
|
||||
if (dart.library.html) 'package:nc_photos/web/platform.dart' as platform;
|
||||
import 'package:nc_photos/mobile/self_signed_cert_manager.dart';
|
||||
import 'package:nc_photos/platform/features.dart' as features;
|
||||
import 'package:nc_photos/touch_manager.dart';
|
||||
import 'package:np_gps_map/np_gps_map.dart';
|
||||
import 'package:np_log/np_log.dart' as np_log;
|
||||
import 'package:np_platform_util/np_platform_util.dart';
|
||||
import 'package:visibility_detector/visibility_detector.dart';
|
||||
|
@ -56,8 +56,6 @@ enum InitIsolateType {
|
|||
flutterIsolate,
|
||||
}
|
||||
|
||||
bool isNewGMapsRenderer() => _isNewGMapsRenderer;
|
||||
|
||||
Future<void> init(InitIsolateType isolateType) async {
|
||||
if (_hasInitedInThisIsolate) {
|
||||
_log.warning("[init] Already initialized in this isolate");
|
||||
|
@ -79,16 +77,7 @@ Future<void> init(InitIsolateType isolateType) async {
|
|||
}
|
||||
await _initDiContainer(isolateType);
|
||||
_initVisibilityDetector();
|
||||
|
||||
if (getRawPlatform() == NpPlatform.android) {
|
||||
if (isolateType == InitIsolateType.main) {
|
||||
try {
|
||||
_isNewGMapsRenderer = await Activity.isNewGMapsRenderer();
|
||||
} catch (e, stackTrace) {
|
||||
_log.severe("[init] Failed while isNewGMapsRenderer", e, stackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
GpsMap.init();
|
||||
|
||||
_hasInitedInThisIsolate = true;
|
||||
}
|
||||
|
@ -237,4 +226,3 @@ Future<sql.SqliteDb> _createDb(InitIsolateType isolateType) async {
|
|||
|
||||
final _log = Logger("app_init");
|
||||
var _hasInitedInThisIsolate = false;
|
||||
var _isNewGMapsRenderer = false;
|
||||
|
|
|
@ -7,8 +7,8 @@ import 'package:nc_photos/entity/pref.dart';
|
|||
import 'package:nc_photos/language_util.dart' as language_util;
|
||||
import 'package:nc_photos/object_extension.dart';
|
||||
import 'package:nc_photos/size.dart';
|
||||
import 'package:nc_photos/widget/gps_map.dart';
|
||||
import 'package:np_codegen/np_codegen.dart';
|
||||
import 'package:np_gps_map/np_gps_map.dart';
|
||||
import 'package:rxdart/rxdart.dart';
|
||||
|
||||
part 'pref_controller.g.dart';
|
||||
|
@ -256,7 +256,7 @@ class PrefController {
|
|||
late final _isViewerForceRotationController =
|
||||
BehaviorSubject.seeded(_c.pref.isViewerForceRotationOr(false));
|
||||
late final _gpsMapProviderController = BehaviorSubject.seeded(
|
||||
GpsMapProvider.fromValue(_c.pref.getGpsMapProviderOr(0)));
|
||||
GpsMapProvider.values[_c.pref.getGpsMapProviderOr(0)]);
|
||||
late final _isAlbumBrowserShowDateController =
|
||||
BehaviorSubject.seeded(_c.pref.isAlbumBrowserShowDateOr(false));
|
||||
late final _isDoubleTapExitController =
|
||||
|
|
12
app/lib/gps_map_util.dart
Normal file
12
app/lib/gps_map_util.dart
Normal file
|
@ -0,0 +1,12 @@
|
|||
import 'package:np_gps_map/np_gps_map.dart';
|
||||
|
||||
extension GpsMapProviderExtension on GpsMapProvider {
|
||||
String toUserString() {
|
||||
switch (this) {
|
||||
case GpsMapProvider.google:
|
||||
return "Google Maps";
|
||||
case GpsMapProvider.osm:
|
||||
return "OpenStreetMap";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +1,8 @@
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:np_async/np_async.dart';
|
||||
|
||||
class Activity {
|
||||
static Future<String?> consumeInitialRoute() =>
|
||||
_methodChannel.invokeMethod("consumeInitialRoute");
|
||||
|
||||
static Future<bool> isNewGMapsRenderer() =>
|
||||
_methodChannel.invokeMethod<bool>("isNewGMapsRenderer").notNull();
|
||||
|
||||
static const _methodChannel = MethodChannel("com.nkming.nc_photos/activity");
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
export 'db_util.dart';
|
||||
export 'download.dart';
|
||||
export 'file_saver.dart';
|
||||
export 'google_gps_map.dart';
|
||||
export 'notification.dart';
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
export 'db_util.dart';
|
||||
export 'download.dart';
|
||||
export 'file_saver.dart';
|
||||
export 'google_gps_map.dart';
|
||||
export 'notification.dart';
|
||||
|
|
|
@ -1,126 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:nc_photos/app_init.dart' as app_init;
|
||||
import 'package:nc_photos/entity/pref.dart';
|
||||
import 'package:nc_photos/mobile/platform.dart'
|
||||
if (dart.library.html) 'package:nc_photos/web/platform.dart' as platform;
|
||||
import 'package:nc_photos/url_launcher_util.dart';
|
||||
import 'package:np_platform_util/np_platform_util.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
enum GpsMapProvider {
|
||||
// the order must not be changed
|
||||
google,
|
||||
osm,
|
||||
;
|
||||
|
||||
static GpsMapProvider fromValue(int value) => GpsMapProvider.values[value];
|
||||
|
||||
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 ||
|
||||
(getRawPlatform() == NpPlatform.android &&
|
||||
!app_init.isNewGMapsRenderer())) {
|
||||
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,
|
||||
),
|
||||
nonRotatedChildren: [
|
||||
AttributionWidget.defaultWidget(
|
||||
source: "OpenStreetMap contributors",
|
||||
),
|
||||
],
|
||||
layers: [
|
||||
TileLayerOptions(
|
||||
urlTemplate: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
),
|
||||
MarkerLayerOptions(
|
||||
markers: [
|
||||
Marker(
|
||||
width: pinSize,
|
||||
height: pinSize,
|
||||
point: centerLl,
|
||||
anchorPos: AnchorPos.align(AnchorAlign.top),
|
||||
builder: (context) => const Image(
|
||||
image: AssetImage("assets/gps_map_pin.png"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final Tuple2<double, double> center;
|
||||
final double zoom;
|
||||
final void Function()? onTap;
|
||||
}
|
|
@ -7,12 +7,13 @@ import 'package:nc_photos/bloc_util.dart';
|
|||
import 'package:nc_photos/controller/pref_controller.dart';
|
||||
import 'package:nc_photos/exception_event.dart';
|
||||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||
import 'package:nc_photos/gps_map_util.dart';
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/widget/fancy_option_picker.dart';
|
||||
import 'package:nc_photos/widget/gps_map.dart';
|
||||
import 'package:nc_photos/widget/page_visibility_mixin.dart';
|
||||
import 'package:np_codegen/np_codegen.dart';
|
||||
import 'package:np_gps_map/np_gps_map.dart';
|
||||
import 'package:np_platform_util/np_platform_util.dart';
|
||||
import 'package:np_ui/np_ui.dart';
|
||||
import 'package:screen_brightness/screen_brightness.dart';
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:logging/logging.dart';
|
|||
import 'package:nc_photos/account.dart';
|
||||
import 'package:nc_photos/app_localizations.dart';
|
||||
import 'package:nc_photos/controller/account_controller.dart';
|
||||
import 'package:nc_photos/controller/pref_controller.dart';
|
||||
import 'package:nc_photos/debug_util.dart';
|
||||
import 'package:nc_photos/di_container.dart';
|
||||
import 'package:nc_photos/entity/collection.dart';
|
||||
|
@ -23,18 +24,19 @@ import 'package:nc_photos/object_extension.dart';
|
|||
import 'package:nc_photos/platform/features.dart' as features;
|
||||
import 'package:nc_photos/set_as_handler.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/stream_util.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/inflate_file_descriptor.dart';
|
||||
import 'package:nc_photos/use_case/list_file_tag.dart';
|
||||
import 'package:nc_photos/use_case/update_property.dart';
|
||||
import 'package:nc_photos/widget/about_geocoding_dialog.dart';
|
||||
import 'package:nc_photos/widget/gps_map.dart';
|
||||
import 'package:nc_photos/widget/handler/add_selection_to_collection_handler.dart';
|
||||
import 'package:nc_photos/widget/list_tile_center_leading.dart';
|
||||
import 'package:nc_photos/widget/photo_date_time_edit_dialog.dart';
|
||||
import 'package:np_codegen/np_codegen.dart';
|
||||
import 'package:np_common/or_null.dart';
|
||||
import 'package:np_geocoder/np_geocoder.dart';
|
||||
import 'package:np_gps_map/np_gps_map.dart';
|
||||
import 'package:np_platform_util/np_platform_util.dart';
|
||||
import 'package:np_string/np_string.dart';
|
||||
import 'package:np_ui/np_ui.dart';
|
||||
|
@ -300,13 +302,17 @@ class _ViewerDetailPaneState extends State<ViewerDetailPane> {
|
|||
duration: k.animationDurationNormal,
|
||||
child: SizedBox(
|
||||
height: 256,
|
||||
child: GpsMap(
|
||||
child: ValueStreamBuilder<GpsMapProvider>(
|
||||
stream: context.read<PrefController>().gpsMapProvider,
|
||||
builder: (context, gpsMapProvider) => GpsMap(
|
||||
providerHint: gpsMapProvider.requireData,
|
||||
center: _gps!,
|
||||
zoom: 16,
|
||||
onTap: _onMapTap,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
|
|
|
@ -594,7 +594,7 @@ packages:
|
|||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_map:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_map
|
||||
sha256: "09010e452bcd8c57ade1b936b79643c4fd599f93b00d1696630f0b919b6f374a"
|
||||
|
@ -799,7 +799,7 @@ packages:
|
|||
source: hosted
|
||||
version: "4.1.0"
|
||||
latlong2:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: latlong2
|
||||
sha256: "08ef7282ba9f76e8495e49e2dc4d653015ac929dce5f92b375a415d30b407ea0"
|
||||
|
@ -990,6 +990,13 @@ packages:
|
|||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
np_gps_map:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "../np_gps_map"
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
np_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
|
|
|
@ -69,7 +69,6 @@ dependencies:
|
|||
flutter_cache_manager: any
|
||||
flutter_colorpicker: ^1.0.3
|
||||
flutter_isolate: ^2.0.4
|
||||
flutter_map: ^2.2.0
|
||||
flutter_staggered_grid_view:
|
||||
git:
|
||||
url: https://gitlab.com/nc-photos/flutter_staggered_grid_view
|
||||
|
@ -85,7 +84,6 @@ dependencies:
|
|||
path: library
|
||||
intl: ^0.17.0
|
||||
kiwi: ^4.1.0
|
||||
latlong2: any
|
||||
logging: ^1.1.1
|
||||
memory_info: ^0.0.3
|
||||
mime: ^1.0.4
|
||||
|
@ -105,6 +103,8 @@ dependencies:
|
|||
path: ../np_collection
|
||||
np_geocoder:
|
||||
path: ../np_geocoder
|
||||
np_gps_map:
|
||||
path: ../np_gps_map
|
||||
np_log:
|
||||
path: ../np_log
|
||||
np_math:
|
||||
|
|
30
np_gps_map/.gitignore
vendored
Normal file
30
np_gps_map/.gitignore
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
/pubspec.lock
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.packages
|
||||
build/
|
30
np_gps_map/.metadata
Normal file
30
np_gps_map/.metadata
Normal file
|
@ -0,0 +1,30 @@
|
|||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled.
|
||||
|
||||
version:
|
||||
revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
channel: stable
|
||||
|
||||
project_type: plugin
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
- platform: android
|
||||
create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
1
np_gps_map/analysis_options.yaml
Normal file
1
np_gps_map/analysis_options.yaml
Normal file
|
@ -0,0 +1 @@
|
|||
include: package:np_lints/np.yaml
|
9
np_gps_map/android/.gitignore
vendored
Normal file
9
np_gps_map/android/.gitignore
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.cxx
|
54
np_gps_map/android/build.gradle
Normal file
54
np_gps_map/android/build.gradle
Normal file
|
@ -0,0 +1,54 @@
|
|||
group 'com.nkming.nc_photos.np_gps_map'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.8.20'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.4.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
namespace 'com.nkming.nc_photos.np_gps_map'
|
||||
compileSdk 33
|
||||
|
||||
defaultConfig {
|
||||
minSdk 21
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "androidx.annotation:annotation:1.6.0"
|
||||
implementation 'com.google.android.gms:play-services-maps:18.1.0'
|
||||
implementation 'com.nkming.nc_photos.np_android_core:np_android_core'
|
||||
}
|
5
np_gps_map/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
np_gps_map/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
2
np_gps_map/android/settings.gradle
Normal file
2
np_gps_map/android/settings.gradle
Normal file
|
@ -0,0 +1,2 @@
|
|||
rootProject.name = 'np_gps_map'
|
||||
includeBuild '../../np_android_core'
|
3
np_gps_map/android/src/main/AndroidManifest.xml
Normal file
3
np_gps_map/android/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,3 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.nkming.nc_photos.np_gps_map">
|
||||
</manifest>
|
|
@ -0,0 +1,26 @@
|
|||
package com.nkming.nc_photos.np_gps_map
|
||||
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
|
||||
internal class GpsMapChannelHandler : MethodChannel.MethodCallHandler {
|
||||
companion object {
|
||||
const val METHOD_CHANNEL = "${K.LIB_ID}/gps_map_method"
|
||||
|
||||
private const val TAG = "GpsMapChannelHandler"
|
||||
}
|
||||
|
||||
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
|
||||
when (call.method) {
|
||||
"isNewGMapsRenderer" -> {
|
||||
result.success(isNewGMapsRenderer)
|
||||
}
|
||||
|
||||
else -> {
|
||||
result.notImplemented()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isNewGMapsRenderer = false
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.nkming.nc_photos.np_gps_map
|
||||
|
||||
internal interface K {
|
||||
companion object {
|
||||
const val LIB_ID = "com.nkming.nc_photos.np_gps_map"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package com.nkming.nc_photos.np_gps_map
|
||||
|
||||
import androidx.annotation.NonNull
|
||||
import com.google.android.gms.maps.MapsInitializer
|
||||
import com.google.android.gms.maps.OnMapsSdkInitializedCallback
|
||||
import com.nkming.nc_photos.np_android_core.logD
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
|
||||
class NpGpsMapPlugin : FlutterPlugin {
|
||||
companion object {
|
||||
private const val TAG = "NpGpsMapPlugin"
|
||||
}
|
||||
|
||||
override fun onAttachedToEngine(
|
||||
@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding
|
||||
) {
|
||||
handler = GpsMapChannelHandler()
|
||||
methodChannel = MethodChannel(
|
||||
flutterPluginBinding.binaryMessenger,
|
||||
GpsMapChannelHandler.METHOD_CHANNEL
|
||||
)
|
||||
methodChannel.setMethodCallHandler(handler)
|
||||
|
||||
MapsInitializer.initialize(
|
||||
flutterPluginBinding.applicationContext,
|
||||
MapsInitializer.Renderer.LATEST, mapCallback
|
||||
)
|
||||
}
|
||||
|
||||
override fun onDetachedFromEngine(
|
||||
@NonNull binding: FlutterPlugin.FlutterPluginBinding
|
||||
) {
|
||||
methodChannel.setMethodCallHandler(null)
|
||||
}
|
||||
|
||||
private lateinit var methodChannel: MethodChannel
|
||||
private lateinit var handler: GpsMapChannelHandler
|
||||
|
||||
private val mapCallback = OnMapsSdkInitializedCallback {
|
||||
handler.isNewGMapsRenderer = when (it) {
|
||||
MapsInitializer.Renderer.LATEST -> {
|
||||
logD(TAG, "Using new map renderer")
|
||||
true
|
||||
}
|
||||
|
||||
MapsInitializer.Renderer.LEGACY -> {
|
||||
logD(TAG, "Using legacy map renderer")
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 5 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
3
np_gps_map/lib/np_gps_map.dart
Normal file
3
np_gps_map/lib/np_gps_map.dart
Normal file
|
@ -0,0 +1,3 @@
|
|||
library np_gps_map;
|
||||
|
||||
export 'src/gps_map.dart';
|
58
np_gps_map/lib/src/gps_map.dart
Normal file
58
np_gps_map/lib/src/gps_map.dart
Normal file
|
@ -0,0 +1,58 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:np_gps_map/src/native.dart';
|
||||
import 'package:np_gps_map/src/native/google_gps_map.dart'
|
||||
if (dart.library.html) 'package:np_gps_map/src/web/google_gps_map.dart';
|
||||
import 'package:np_gps_map/src/osm_gps_map.dart';
|
||||
import 'package:np_platform_util/np_platform_util.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
enum GpsMapProvider {
|
||||
google,
|
||||
osm,
|
||||
;
|
||||
}
|
||||
|
||||
class GpsMap extends StatelessWidget {
|
||||
const GpsMap({
|
||||
super.key,
|
||||
required this.providerHint,
|
||||
required this.center,
|
||||
required this.zoom,
|
||||
this.onTap,
|
||||
});
|
||||
|
||||
static void init() {
|
||||
if (getRawPlatform() == NpPlatform.android) {
|
||||
Native.isNewGMapsRenderer().then((value) => _isNewGMapsRenderer = value);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (providerHint == GpsMapProvider.osm ||
|
||||
(getRawPlatform() == NpPlatform.android && !_isNewGMapsRenderer)) {
|
||||
return OsmGpsMap(
|
||||
center: center,
|
||||
zoom: zoom,
|
||||
onTap: onTap,
|
||||
);
|
||||
} else {
|
||||
return GoogleGpsMap(
|
||||
center: center,
|
||||
zoom: zoom,
|
||||
onTap: onTap,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// The backend to provide the actual map. This works as a hint only, the
|
||||
/// actual choice may be different depending on the runtime environment
|
||||
final GpsMapProvider providerHint;
|
||||
|
||||
/// A pair of latitude and longitude coordinates, stored as degrees
|
||||
final Tuple2<double, double> center;
|
||||
final double zoom;
|
||||
final void Function()? onTap;
|
||||
|
||||
static bool _isNewGMapsRenderer = false;
|
||||
}
|
1
np_gps_map/lib/src/k.dart
Normal file
1
np_gps_map/lib/src/k.dart
Normal file
|
@ -0,0 +1 @@
|
|||
const libId = "com.nkming.nc_photos.np_gps_map";
|
10
np_gps_map/lib/src/native.dart
Normal file
10
np_gps_map/lib/src/native.dart
Normal file
|
@ -0,0 +1,10 @@
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:np_async/np_async.dart';
|
||||
import 'package:np_gps_map/src/k.dart' as k;
|
||||
|
||||
class Native {
|
||||
static Future<bool> isNewGMapsRenderer() =>
|
||||
_methodChannel.invokeMethod<bool>("isNewGMapsRenderer").notNull();
|
||||
|
||||
static const _methodChannel = MethodChannel("${k.libId}/gps_map_method");
|
||||
}
|
|
@ -4,14 +4,14 @@ import 'package:tuple/tuple.dart';
|
|||
|
||||
class GoogleGpsMap extends StatelessWidget {
|
||||
const GoogleGpsMap({
|
||||
Key? key,
|
||||
super.key,
|
||||
required this.center,
|
||||
required this.zoom,
|
||||
this.onTap,
|
||||
}) : super(key: key);
|
||||
});
|
||||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
Widget build(BuildContext context) {
|
||||
final centerLl = LatLng(center.item1, center.item2);
|
||||
return GoogleMap(
|
||||
compassEnabled: false,
|
70
np_gps_map/lib/src/osm_gps_map.dart
Normal file
70
np_gps_map/lib/src/osm_gps_map.dart
Normal file
|
@ -0,0 +1,70 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
class OsmGpsMap extends StatelessWidget {
|
||||
const OsmGpsMap({
|
||||
super.key,
|
||||
required this.center,
|
||||
required this.zoom,
|
||||
this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const double pinSize = 48;
|
||||
final centerLl = LatLng(center.item1, center.item2);
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
launchUrlString(
|
||||
"https://www.openstreetmap.org/?mlat=${center.item1}&mlon=${center.item2}#map=${zoom.toInt()}/${center.item1}/${center.item2}",
|
||||
mode: LaunchMode.externalApplication,
|
||||
);
|
||||
},
|
||||
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,
|
||||
),
|
||||
nonRotatedChildren: [
|
||||
AttributionWidget.defaultWidget(
|
||||
source: "OpenStreetMap contributors",
|
||||
),
|
||||
],
|
||||
layers: [
|
||||
TileLayerOptions(
|
||||
urlTemplate: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
),
|
||||
MarkerLayerOptions(
|
||||
markers: [
|
||||
Marker(
|
||||
width: pinSize,
|
||||
height: pinSize,
|
||||
point: centerLl,
|
||||
anchorPos: AnchorPos.align(AnchorAlign.top),
|
||||
builder: (_) => const Image(
|
||||
image: AssetImage(
|
||||
"packages/np_gps_map/assets/gps_map_pin.png"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final Tuple2<double, double> center;
|
||||
final double zoom;
|
||||
final void Function()? onTap;
|
||||
}
|
|
@ -2,20 +2,20 @@
|
|||
import 'dart:html';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:nc_photos/mobile/ui_hack.dart' if (dart.library.html) 'dart:ui'
|
||||
import 'package:np_gps_map/src/ui_hack.dart' if (dart.library.html) 'dart:ui'
|
||||
as ui;
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class GoogleGpsMap extends StatefulWidget {
|
||||
const GoogleGpsMap({
|
||||
Key? key,
|
||||
super.key,
|
||||
required this.center,
|
||||
required this.zoom,
|
||||
this.onTap,
|
||||
}) : super(key: key);
|
||||
});
|
||||
|
||||
@override
|
||||
createState() => _GoogleGpsMapState();
|
||||
State<StatefulWidget> createState() => _GoogleGpsMapState();
|
||||
|
||||
final Tuple2<double, double> center;
|
||||
final double zoom;
|
||||
|
@ -24,18 +24,18 @@ class GoogleGpsMap extends StatefulWidget {
|
|||
|
||||
class _GoogleGpsMapState extends State<GoogleGpsMap> {
|
||||
@override
|
||||
initState() {
|
||||
void initState() {
|
||||
super.initState();
|
||||
final iframe = IFrameElement()
|
||||
..src = "https://www.google.com/maps/embed/v1/place?key=$_apiKey"
|
||||
"&q=${widget.center.item1},${widget.center.item2}"
|
||||
"&zoom=${widget.zoom}"
|
||||
..style.border = "none";
|
||||
ui.platformViewRegistry.registerViewFactory(viewType, (viewId) => iframe);
|
||||
ui.platformViewRegistry.registerViewFactory(viewType, (_) => iframe);
|
||||
}
|
||||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
Widget build(BuildContext context) {
|
||||
return HtmlElementView(
|
||||
viewType: viewType,
|
||||
);
|
35
np_gps_map/pubspec.yaml
Normal file
35
np_gps_map/pubspec.yaml
Normal file
|
@ -0,0 +1,35 @@
|
|||
name: np_gps_map
|
||||
description: A new Flutter package project.
|
||||
version: 0.0.1
|
||||
homepage:
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: '>=2.19.6 <3.0.0'
|
||||
flutter: ">=3.3.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_map: ^2.2.0
|
||||
google_maps_flutter: ^2.2.8
|
||||
latlong2: any
|
||||
np_async:
|
||||
path: ../np_async
|
||||
np_platform_util:
|
||||
path: ../np_platform_util
|
||||
tuple: ^2.0.1
|
||||
url_launcher: ^6.1.11
|
||||
|
||||
dev_dependencies:
|
||||
np_lints:
|
||||
path: ../np_lints
|
||||
|
||||
flutter:
|
||||
plugin:
|
||||
platforms:
|
||||
android:
|
||||
package: com.nkming.nc_photos.np_gps_map
|
||||
pluginClass: NpGpsMapPlugin
|
||||
assets:
|
||||
- assets/
|
Loading…
Reference in a new issue