├── lib ├── every_door_plugin.dart ├── plugins │ ├── providers.dart │ ├── ext_overlay.dart │ ├── events.dart │ ├── preferences.dart │ ├── every_door_plugin.dart │ ├── interface.dart │ └── bindings │ │ ├── plugins │ │ ├── providers.eval.dart │ │ ├── every_door_plugin.eval.dart │ │ ├── events.eval.dart │ │ ├── ext_overlay.eval.dart │ │ ├── preferences.eval.dart │ │ └── interface.eval.dart │ │ ├── helpers │ │ ├── plugin_i18n.eval.dart │ │ └── multi_icon.eval.dart │ │ ├── every_door_eval.dart │ │ ├── models │ │ ├── note.eval.dart │ │ └── imagery.eval.dart │ │ └── widgets │ │ └── poi_marker.eval.dart ├── widgets │ ├── poi_marker.dart │ ├── entrance_markers.dart │ ├── map.dart │ └── map_button.dart ├── helpers │ ├── yaml_map.dart │ ├── auth │ │ ├── oauth2.dart │ │ ├── controller.dart │ │ └── provider.dart │ ├── multi_icon.dart │ ├── plugin_i18n.dart │ ├── legend.dart │ ├── draw_style.dart │ ├── tags │ │ ├── main_key.dart │ │ ├── element_kind.dart │ │ └── tag_matcher.dart │ └── geometry │ │ └── geometry.dart ├── screens │ └── modes │ │ └── definitions │ │ ├── notes.dart │ │ ├── classic.dart │ │ ├── amenity.dart │ │ ├── base.dart │ │ ├── micro.dart │ │ └── entrances.dart ├── models │ ├── imagery.dart │ ├── plugin.dart │ ├── version.dart │ ├── osm_element.dart │ ├── note.dart │ └── amenity.dart └── cli │ └── package.dart ├── CHANGELOG.md ├── example ├── generate.dart ├── .gitignore ├── pubspec.yaml └── lib │ └── main.dart ├── bin └── every_door_plugin.dart ├── analysis_options.yaml ├── .metadata ├── .gitignore ├── LICENSE ├── pubspec.yaml └── README.md /lib/every_door_plugin.dart: -------------------------------------------------------------------------------- 1 | export 'helpers/yaml_map.dart'; -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 2 | 3 | * Initial version that can package static plugins. 4 | -------------------------------------------------------------------------------- /example/generate.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/cli/package.dart'; 2 | Future main() => Packager().run(); 3 | -------------------------------------------------------------------------------- /bin/every_door_plugin.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/cli/package.dart'; 2 | 3 | Future main(List args) async { 4 | await Packager().run(); 5 | } 6 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | # Additional information about this file can be found at 4 | # https://dart.dev/guides/language/analysis-options 5 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter/Dart/Pub related 2 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 3 | /pubspec.lock 4 | **/doc/api/ 5 | .dart_tool/ 6 | .flutter-plugins-dependencies 7 | /build/ 8 | /coverage/ 9 | /dist/ 10 | *.edp 11 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "9f455d2486bcb28cad87b062475f42edc959f636" 8 | channel: "stable" 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /lib/plugins/providers.dart: -------------------------------------------------------------------------------- 1 | import 'package:latlong2/latlong.dart' show LatLng; 2 | 3 | abstract class PluginProviders { 4 | /// Get the current location of the main screen. 5 | LatLng get location; 6 | 7 | /// Learn whether we're moving the map automatically with the user 8 | /// movement. 9 | bool get isTracking; 10 | 11 | /// Get the compass direction. 12 | double? get compass; 13 | 14 | /// Teleports the map to the given location. 15 | set location(LatLng value); 16 | 17 | /// Changes the map zoom level. 18 | set zoom(double value); 19 | 20 | // TODO: do we need watching? 21 | } 22 | -------------------------------------------------------------------------------- /lib/widgets/poi_marker.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class NumberedMarker extends StatelessWidget { 4 | final int? index; 5 | final Color color; 6 | 7 | const NumberedMarker({super.key, this.index, this.color = Colors.white}); 8 | 9 | @override 10 | Widget build(BuildContext context) => Container(); 11 | } 12 | 13 | class ColoredMarker extends StatelessWidget { 14 | final Color color; 15 | final bool isIncomplete; 16 | 17 | const ColoredMarker( 18 | {super.key, this.color = Colors.black, this.isIncomplete = false}); 19 | 20 | @override 21 | Widget build(BuildContext context) => Container(); 22 | } 23 | -------------------------------------------------------------------------------- /lib/plugins/ext_overlay.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/models/imagery.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_map/flutter_map.dart'; 4 | 5 | class ExtOverlay extends Imagery { 6 | final Widget Function(BuildContext context, dynamic data) build; 7 | final int updateInMeters; 8 | final Future Function(LatLngBounds)? update; 9 | 10 | ExtOverlay({ 11 | required super.id, 12 | super.attribution, 13 | this.updateInMeters = 0, 14 | required this.build, 15 | this.update, 16 | }) : super(overlay: true); 17 | 18 | @override 19 | Widget buildLayer({bool reset = false}) => Placeholder(); 20 | } -------------------------------------------------------------------------------- /lib/helpers/yaml_map.dart: -------------------------------------------------------------------------------- 1 | import 'package:yaml/yaml.dart'; 2 | 3 | extension YamlMapConverter on YamlMap { 4 | dynamic _convertNode(YamlNode v) { 5 | if (v is YamlMap) { 6 | return v.toMap(); 7 | } else if (v is YamlList) { 8 | return v.nodes.map((e) => _convertNode(e)).toList(); 9 | } else if (v is YamlScalar) { 10 | return v.value; 11 | } else { 12 | return v; 13 | } 14 | } 15 | 16 | Map toMap() { 17 | var map = {}; 18 | nodes.forEach((k, v) { 19 | if (k is YamlScalar) { 20 | map[k.value.toString()] = _convertNode(v); 21 | } 22 | }); 23 | return map; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 26 | /pubspec.lock 27 | **/doc/api/ 28 | .dart_tool/ 29 | .flutter-plugins-dependencies 30 | /build/ 31 | /coverage/ 32 | 33 | # My files 34 | /dist/ 35 | *.edp 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2025, Ilya Zverev 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /lib/screens/modes/definitions/notes.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/multi_icon.dart'; 2 | import 'package:every_door_plugin/models/note.dart'; 3 | import 'package:every_door_plugin/models/plugin.dart'; 4 | import 'package:every_door_plugin/plugins/interface.dart'; 5 | import 'package:every_door_plugin/screens/modes/definitions/base.dart'; 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter_map/flutter_map.dart'; 8 | 9 | abstract class NotesModeDefinition extends BaseModeDefinition { 10 | List notes = []; 11 | 12 | NotesModeDefinition.fromPlugin(EveryDoorApp app); 13 | 14 | @override 15 | MultiIcon getIcon(BuildContext context, bool outlined) => MultiIcon(); 16 | 17 | @override 18 | Future updateNearest(LatLngBounds bounds) async { 19 | } 20 | 21 | @override 22 | void updateFromJson(Map data, Plugin plugin) { 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/plugins/events.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/screens/modes/definitions/base.dart'; 2 | import 'package:latlong2/latlong.dart' show LatLng; 3 | 4 | /// Plugin events wrapper. Use this class to listen to events. Listeners 5 | /// are automatically deactivated when the plugin is inactive. All callback 6 | /// should be asynchronous functions, even when they don't use await. 7 | class PluginEvents { 8 | /// Listen to editing mode instantiations. The [callback] is called on 9 | /// each mode when initializing the plugin, and then every time a new 10 | /// mode is added. The [callback] should be an async function. 11 | void onModeCreated(Function(BaseModeDefinition mode) callback) {} 12 | 13 | /// Invoked when the "upload" button is pressed. 14 | void onUpload(Function() callback) {} 15 | 16 | /// Invoked when the "download" button is pressed. 17 | void onDownload(Function(LatLng) callback) {} 18 | } 19 | -------------------------------------------------------------------------------- /lib/plugins/preferences.dart: -------------------------------------------------------------------------------- 1 | /// Shadows the shared_preferences module from plugins. Nothing wrong with 2 | /// using it directly, but this allows us to track preferences by plugin. 3 | /// Basically adds a prefix to every key, and accesses the app-wide 4 | /// [SharedPreferencesWithCache] instance. 5 | class PluginPreferences { 6 | Future setString(String name, String value) async { 7 | } 8 | 9 | Future setInt(String name, int value) async {} 10 | 11 | Future setBool(String name, bool value) async {} 12 | 13 | Future setDouble(String name, double value) async {} 14 | 15 | Future setStringList(String name, List value) async {} 16 | 17 | String? getString(String name) => null; 18 | 19 | int? getInt(String name) => null; 20 | 21 | bool? getBool(String name) => null; 22 | 23 | double? getDouble(String name) => null; 24 | 25 | List? getStringList(String name) => null; 26 | } 27 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: every_door_plugin 2 | description: "Every Door plugin framework" 3 | version: 1.2.0 4 | homepage: https://github.com/zverik/every_door_plugin 5 | 6 | environment: 7 | sdk: ^3.9.0 8 | flutter: "^3.35.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | archive: ^4.0.7 14 | dart_eval: ^0.8.2 15 | flutter_eval: ^0.8.1 16 | flutter_map_eval: 17 | git: 18 | url: https://github.com/Zverik/flutter_map_eval.git 19 | ref: main 20 | path: ^1.9.1 21 | logging: ^1.0.2 22 | yaml: ^3.1.3 23 | yaml_writer: ^2.1.0 24 | 25 | dev_dependencies: 26 | flutter_test: 27 | sdk: flutter 28 | flutter_lints: ^6.0.0 29 | 30 | dependency_overrides: 31 | dart_eval: 32 | git: 33 | url: https://github.com/Zverik/dart_eval.git 34 | ref: operators 35 | flutter_eval: 36 | git: 37 | url: https://github.com/Zverik/flutter_eval.git 38 | ref: no_icons 39 | 40 | executables: 41 | edp: every_door_plugin 42 | -------------------------------------------------------------------------------- /lib/helpers/auth/oauth2.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/auth/provider.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// Authentication provider for services with OAuth2. Which are 5 | /// basically the most of them, including OpenStreetMap. 6 | abstract class OAuth2AuthProvider extends AuthProvider { 7 | OAuth2AuthProvider({ 8 | required String authorizeUrl, 9 | required String tokenUrl, 10 | required String clientId, 11 | required String clientSecret, 12 | required List scopes, 13 | }); 14 | 15 | @override 16 | AuthToken tokenFromJson(Map data) { 17 | throw UnimplementedError(); 18 | } 19 | 20 | @override 21 | Future login(BuildContext context) async => null; 22 | 23 | @override 24 | Future logout(AuthToken token) async { 25 | } 26 | 27 | @override 28 | Future refreshToken(AuthToken token) async => token; 29 | 30 | @override 31 | Map getHeaders(AuthToken token) => {}; 32 | } 33 | -------------------------------------------------------------------------------- /lib/helpers/multi_icon.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | /// This class encapsulates monochrome icons. 5 | /// It replaces IconData class, allowing for raster 6 | /// and vector images. An image should be rectangular, 7 | /// recommended dimensions are 256×256. 8 | class MultiIcon { 9 | final String? tooltip; 10 | 11 | MultiIcon({ 12 | IconData? fontIcon, 13 | String? emoji, 14 | Uint8List? imageData, 15 | Uint8List? svgData, 16 | Uint8List? siData, 17 | String? imageUrl, 18 | String? asset, 19 | this.tooltip, 20 | }); 21 | 22 | MultiIcon withTooltip(String? tooltip) => this; 23 | 24 | Widget getWidget({ 25 | BuildContext? context, 26 | double? size, 27 | Color? color, 28 | String? semanticLabel, 29 | bool icon = true, 30 | bool fixedSize = true, 31 | }) { 32 | return SizedBox(width: size, height: size); 33 | } 34 | 35 | @override 36 | String toString() { 37 | return 'MultiIcon(empty)'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/screens/modes/definitions/classic.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/plugins/interface.dart'; 2 | import 'package:every_door_plugin/models/amenity.dart'; 3 | import 'package:every_door_plugin/models/plugin.dart'; 4 | import 'package:every_door_plugin/screens/modes/definitions/base.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:flutter_map/flutter_map.dart'; 7 | import 'package:latlong2/latlong.dart' show LatLng; 8 | 9 | abstract class ClassicModeDefinition extends BaseModeDefinition { 10 | List nearestPOI = []; 11 | 12 | ClassicModeDefinition(); 13 | ClassicModeDefinition.fromPlugin(EveryDoorApp plugin); 14 | 15 | @override 16 | void updateFromJson(Map data, Plugin plugin) {} 17 | 18 | @override 19 | updateNearest(LatLngBounds bounds) async { 20 | } 21 | 22 | void openEditor({ 23 | required BuildContext context, 24 | OsmChange? element, 25 | LatLng? location, 26 | }) async { 27 | } 28 | 29 | Widget buildMarker(OsmChange element) => Container(); 30 | } 31 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: panoramax_demo 2 | description: "Panoramax Photo Browser Demo" 3 | version: 1.0.0 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ^3.9.0 8 | flutter: "^3.35.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | every_door_plugin: 14 | path: ../ 15 | 16 | dev_dependencies: 17 | flutter_test: 18 | sdk: flutter 19 | flutter_lints: ^6.0.0 20 | 21 | dependency_overrides: 22 | dart_eval: 23 | path: ../../dart_eval 24 | #git: 25 | # url: https://github.com/Zverik/dart_eval.git 26 | # ref: operators 27 | flutter_eval: 28 | git: 29 | url: https://github.com/Zverik/flutter_eval.git 30 | ref: no_icons 31 | 32 | every_door: 33 | description: | 34 | A test plugin for code functionality. Adds a "P" button to 35 | the micromapping mode, and displays camera markers when there 36 | are photos on Panomarax French instance. When tapping on a photo, 37 | you can see it in a popup panel. 38 | icon: panoramax_favicon.svg 39 | accesses: https://panoramax.openstreetmap.fr/api/ 40 | api: 1.2 41 | -------------------------------------------------------------------------------- /lib/plugins/every_door_plugin.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/plugins/interface.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// Parent class for every plugin. None of the methods need to be implemented, 5 | /// although it would be weird. 6 | class EveryDoorPlugin { 7 | /// Set up listeners and stuff. This gets called when the plugin is enabled, 8 | /// either during the start-up, or after the installation. 9 | Future install(EveryDoorApp app) async {} 10 | 11 | /// Uninstall plugin. Usually does not need to be overridden, but can e.g. store 12 | /// data somewhere. Called when the plugin is manually uninstalled. 13 | /// NOT called when the app is closed and unloaded. 14 | Future uninstall(EveryDoorApp app) async {} 15 | 16 | /// Returns a widget for the plugin settings. The best option would be 17 | /// to return a [Column] with a list of [ListTile]. 18 | /// Use [EveryDoorApp.preferences] for storing those. Use 19 | /// [EveryDoorApp.repaint] method when you usually would call setState(). 20 | Widget? buildSettingsPane(EveryDoorApp app, BuildContext context) { 21 | return null; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/helpers/plugin_i18n.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// Localizations wrapper for passing to various parts of code that need 4 | /// only small parts of the metadata tree. For example, a tree preset 5 | /// would need "preset.tree" branch for translations. This class allows 6 | /// to hide the context. 7 | abstract class PluginLocalizationsBranch { 8 | String translateCtx( 9 | BuildContext context, 10 | String key, { 11 | Map? args, 12 | }); 13 | 14 | String translate(Locale locale, String key, {Map? args}); 15 | 16 | List translateList(Locale locale, String key); 17 | } 18 | 19 | class PluginLocalizations { 20 | String translate( 21 | Locale locale, 22 | String key, { 23 | Map? args, 24 | Map? data, 25 | }) => key; 26 | 27 | List translateList( 28 | Locale locale, 29 | String key, { 30 | Map? data, 31 | }) => []; 32 | 33 | String translateN( 34 | Locale locale, 35 | String key, 36 | int count, { 37 | Map? args, 38 | Map? data, 39 | }) => key; 40 | } 41 | -------------------------------------------------------------------------------- /lib/screens/modes/definitions/amenity.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/multi_icon.dart'; 2 | import 'package:every_door_plugin/models/amenity.dart'; 3 | import 'package:every_door_plugin/models/plugin.dart'; 4 | import 'package:every_door_plugin/plugins/interface.dart'; 5 | import 'package:every_door_plugin/screens/modes/definitions/base.dart'; 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter_map/flutter_map.dart'; 8 | import 'package:latlong2/latlong.dart'; 9 | 10 | abstract class AmenityModeDefinition extends BaseModeDefinition { 11 | static const _kAmenitiesInList = 12; 12 | 13 | List nearestPOI = []; 14 | List otherPOI = []; 15 | 16 | AmenityModeDefinition(); 17 | AmenityModeDefinition.fromPlugin(EveryDoorApp app); 18 | 19 | int get maxTileCount => _kAmenitiesInList; 20 | 21 | @override 22 | MultiIcon getIcon(BuildContext context, bool outlined) => MultiIcon(); 23 | 24 | @override 25 | updateNearest(LatLngBounds bounds) async { 26 | } 27 | 28 | void openEditor(BuildContext context, LatLng location) async { 29 | } 30 | 31 | Widget buildMarker(int index, OsmChange element) => Container(); 32 | 33 | bool isCountedOld(OsmChange element, int age) => false; 34 | 35 | @override 36 | void updateFromJson(Map data, Plugin plugin) { 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/screens/modes/definitions/base.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/multi_icon.dart'; 2 | import 'package:every_door_plugin/helpers/tags/element_kind.dart'; 3 | import 'package:every_door_plugin/models/amenity.dart'; 4 | import 'package:every_door_plugin/models/imagery.dart'; 5 | import 'package:every_door_plugin/models/plugin.dart'; 6 | import 'package:every_door_plugin/widgets/map_button.dart'; 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter_map/flutter_map.dart' show LatLngBounds; 9 | 10 | abstract class BaseModeDefinition extends ChangeNotifier { 11 | String get name; 12 | 13 | MultiIcon getIcon(BuildContext context, bool outlined); 14 | 15 | bool isOurKind(OsmChange element) => false; 16 | 17 | final Iterable overlays = []; 18 | final Iterable buttons = []; 19 | 20 | void addMapButton(MapButton button) { 21 | } 22 | 23 | void removeMapButton(String id) { 24 | } 25 | 26 | void addOverlay(Imagery imagery) { 27 | } 28 | 29 | Future> getNearestChanges(LatLngBounds bounds, 30 | {int maxCount = 200, bool filter = true}) async => []; 31 | 32 | Future updateNearest(LatLngBounds bounds); 33 | 34 | void updateFromJson(Map data, Plugin plugin); 35 | 36 | List? parseKinds(dynamic data) => null; 37 | 38 | List mapLayers() => []; 39 | } 40 | -------------------------------------------------------------------------------- /lib/screens/modes/definitions/micro.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/multi_icon.dart'; 2 | import 'package:every_door_plugin/models/amenity.dart'; 3 | import 'package:every_door_plugin/models/plugin.dart'; 4 | import 'package:every_door_plugin/helpers/legend.dart'; 5 | import 'package:every_door_plugin/plugins/interface.dart'; 6 | import 'package:every_door_plugin/screens/modes/definitions/base.dart'; 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter_map/flutter_map.dart'; 9 | import 'package:latlong2/latlong.dart'; 10 | 11 | abstract class MicromappingModeDefinition extends BaseModeDefinition { 12 | static const kMicroStuffInList = 24; 13 | 14 | List nearestPOI = []; 15 | List otherPOI = []; 16 | bool enableZoomingIn = true; 17 | LegendController legend = LegendController(); 18 | 19 | MicromappingModeDefinition.fromPlugin(EveryDoorApp app); 20 | 21 | @override 22 | MultiIcon getIcon(BuildContext context, bool outlined) => MultiIcon(); 23 | 24 | void updateLegend(BuildContext context) { 25 | } 26 | 27 | @override 28 | bool isOurKind(OsmChange element) => false; 29 | 30 | @override 31 | updateNearest(LatLngBounds bounds) async { 32 | } 33 | 34 | void openEditor(BuildContext context, LatLng location) async { 35 | } 36 | 37 | @override 38 | void updateFromJson(Map data, Plugin plugin) { 39 | } 40 | 41 | Widget buildMarker(int index, OsmChange element, bool isZoomedIn) => Container(); 42 | } 43 | -------------------------------------------------------------------------------- /lib/helpers/auth/controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/auth/provider.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// This controller manages an [AuthProvider], saving a token to the 5 | /// local storage and keeping user details in [value] ready to display. 6 | class AuthController extends ValueNotifier { 7 | /// Controller name. Should be overridden, and unique, otherwise 8 | /// tokens would get mixed up. 9 | final String name; 10 | 11 | final AuthProvider provider; 12 | 13 | AuthController(this.name, this.provider): super(null); 14 | 15 | bool get authorized => value != null; 16 | 17 | String get endpoint => provider.endpoint; 18 | 19 | Future loadData() async { 20 | } 21 | 22 | Future login(BuildContext context) async { 23 | } 24 | 25 | Future logout() async { 26 | } 27 | 28 | Future fetchToken(BuildContext? context) async { 29 | throw AuthException("User is not logged in"); 30 | } 31 | 32 | Future> getAuthHeaders(BuildContext? context) async { 33 | throw AuthException('Could not use the saved token, please re-login.'); 34 | } 35 | 36 | Future getApiKey(BuildContext? context) async { 37 | throw AuthException('Could not use the saved token, please re-login.'); 38 | } 39 | 40 | String get tokenKey => 'authToken_$name'; 41 | 42 | Future loadToken() async { 43 | return null; 44 | } 45 | 46 | Future saveToken(AuthToken? token) async { 47 | } 48 | } -------------------------------------------------------------------------------- /lib/widgets/entrance_markers.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/multi_icon.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_map/flutter_map.dart'; 4 | import 'package:latlong2/latlong.dart'; 5 | 6 | class SizedMarker { 7 | final Widget child; 8 | 9 | final double width; 10 | 11 | final double height; 12 | 13 | final bool rotate; 14 | 15 | final Alignment alignment; 16 | 17 | const SizedMarker({ 18 | required this.child, 19 | required this.width, 20 | required this.height, 21 | this.rotate = false, 22 | this.alignment = Alignment.center, 23 | }); 24 | 25 | Marker buildMarker({Key? key, required LatLng point}) { 26 | return Marker( 27 | key: key, 28 | point: point, 29 | width: width, 30 | height: height, 31 | rotate: rotate, 32 | child: child, 33 | alignment: alignment, 34 | ); 35 | } 36 | } 37 | 38 | class BuildingMarker extends SizedMarker { 39 | BuildingMarker({bool isComplete = false, required String label}) 40 | : super( 41 | width: 120.0, 42 | height: 60.0, 43 | rotate: true, 44 | child: Center(child: Container()), 45 | ); 46 | } 47 | 48 | class AddressMarker extends SizedMarker { 49 | AddressMarker({required String label}) 50 | : super( 51 | rotate: true, 52 | width: 90.0, 53 | height: 50.0, 54 | child: Center(child: Container()), 55 | ); 56 | } 57 | 58 | class EntranceMarker extends SizedMarker { 59 | EntranceMarker({bool isComplete = false}) 60 | : super(width: 50.0, height: 50.0, child: Center(child: Container())); 61 | } 62 | 63 | class IconMarker extends SizedMarker { 64 | IconMarker(MultiIcon icon) 65 | : super( 66 | width: 50.0, 67 | height: 50.0, 68 | child: Center(child: icon.getWidget(size: 30.0, icon: false)), 69 | ); 70 | } 71 | -------------------------------------------------------------------------------- /lib/screens/modes/definitions/entrances.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/multi_icon.dart'; 2 | import 'package:every_door_plugin/helpers/tags/element_kind.dart'; 3 | import 'package:every_door_plugin/models/amenity.dart'; 4 | import 'package:every_door_plugin/models/plugin.dart'; 5 | import 'package:every_door_plugin/plugins/interface.dart'; 6 | import 'package:every_door_plugin/screens/modes/definitions/base.dart'; 7 | import 'package:every_door_plugin/widgets/entrance_markers.dart'; 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_map/flutter_map.dart'; 10 | import 'package:latlong2/latlong.dart'; 11 | 12 | abstract class EntrancesModeDefinition extends BaseModeDefinition { 13 | List nearest = []; 14 | LatLng? newLocation; 15 | 16 | EntrancesModeDefinition.fromPlugin(EveryDoorApp app); 17 | 18 | @override 19 | String get name => "entrances"; 20 | 21 | @override 22 | MultiIcon getIcon(BuildContext context, bool outlined) => MultiIcon(); 23 | 24 | ElementKindImpl getOurKind(OsmChange element) => ElementKind.entrance; 25 | 26 | @override 27 | bool isOurKind(OsmChange element) => 28 | getOurKind(element) != ElementKind.unknown; 29 | 30 | @override 31 | Future updateNearest(LatLngBounds bounds) async { 32 | } 33 | 34 | double get adjustZoomPrimary => 0.0; 35 | 36 | double get adjustZoomSecondary => 0.0; 37 | 38 | SizedMarker? buildMarker(OsmChange element); 39 | 40 | MultiIcon? getButton(BuildContext context, bool isPrimary); 41 | 42 | void openEditor({ 43 | required BuildContext context, 44 | OsmChange? element, 45 | LatLng? location, 46 | bool? isPrimary, 47 | }); 48 | 49 | Widget disambiguationLabel(BuildContext context, OsmChange element) { 50 | return Padding( 51 | padding: const EdgeInsets.symmetric(vertical: 5.0), 52 | child: Text(element.typeAndName, style: TextStyle(fontSize: 20.0)), 53 | ); 54 | } 55 | 56 | @override 57 | void updateFromJson(Map data, Plugin plugin) { 58 | } 59 | } -------------------------------------------------------------------------------- /lib/widgets/map.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/widgets/map_button.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_map/flutter_map.dart'; 4 | import 'package:latlong2/latlong.dart' show LatLng; 5 | 6 | class CustomMapController { 7 | Function(Iterable)? zoomListener; 8 | MapController? mapController; 9 | GlobalKey? mapKey; 10 | 11 | void setLocation({LatLng? location, double? zoom}) { 12 | if (mapController != null) { 13 | mapController!.move(location ?? mapController!.camera.center, 14 | zoom ?? mapController!.camera.zoom); 15 | } 16 | } 17 | 18 | void zoomToFit(Iterable locations) { 19 | if (locations.isNotEmpty) { 20 | if (zoomListener != null) zoomListener!(locations); 21 | } 22 | } 23 | } 24 | 25 | /// General map widget for every map in Every Door. Encloses layer management, 26 | /// interaction, additional buttons etc etc. 27 | class CustomMap extends StatefulWidget { 28 | final void Function(LatLng, double Function(LatLng))? onTap; 29 | final CustomMapController? controller; 30 | final List layers; 31 | final List buttons; 32 | final bool drawZoomButtons; 33 | 34 | /// When there is a floating button on the screen, zoom buttons 35 | /// need to be moved higher. 36 | final bool hasFloatingButton; 37 | final bool drawStandardButtons; 38 | final bool drawPinMarker; 39 | final bool faintWalkPath; 40 | final bool interactive; 41 | final bool track; 42 | final bool onlyOSM; 43 | final bool allowRotation; 44 | final bool updateState; 45 | final bool switchToNavigate; 46 | 47 | const CustomMap({ 48 | super.key, 49 | this.onTap, 50 | this.controller, 51 | this.layers = const [], 52 | this.buttons = const [], 53 | this.drawZoomButtons = true, 54 | this.hasFloatingButton = false, 55 | this.drawStandardButtons = true, 56 | this.drawPinMarker = true, 57 | this.faintWalkPath = true, 58 | this.interactive = true, 59 | this.track = true, 60 | this.onlyOSM = false, 61 | this.allowRotation = true, 62 | this.switchToNavigate = true, 63 | this.updateState = false, 64 | }); 65 | 66 | @override 67 | State createState() => _CustomMapState(); 68 | } 69 | 70 | class _CustomMapState extends State { 71 | @override 72 | Widget build(BuildContext context) { 73 | throw UnimplementedError(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /lib/models/imagery.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/multi_icon.dart'; 2 | import 'package:flutter/widgets.dart' show Widget, protected; 3 | 4 | /// Imagery category, a subset of the Editor Layer Index categories. 5 | enum ImageryCategory { 6 | photo, 7 | map, 8 | other, 9 | } 10 | 11 | /// A data container for an imagery layer. Fields are based on the editor 12 | /// layer index, and just the identifier and type are required. This is 13 | /// the super-class for the multitude of implementations, including TMS, 14 | /// WMS, and vector tiles. 15 | abstract class Imagery { 16 | /// Package name to send to servers. 17 | @protected 18 | final String kUserAgentPackageName = 'info.zverev.ilya.every_door'; 19 | 20 | /// Identifier of the imagery. Should be unique for every layer. 21 | final String id; 22 | 23 | /// Imagery category. Not really used anywhere. 24 | final ImageryCategory? category; 25 | 26 | /// Display name, shown in lists when choosing an imagery layer. 27 | final String? name; 28 | 29 | /// Icon to display. 30 | final MultiIcon? icon; 31 | 32 | /// Imagery attribution. Displayed in a corner for most maps. 33 | final String? attribution; 34 | 35 | /// Whether this imagery is the best imagery for the region. 36 | /// Might affect sorting. 37 | final bool best; 38 | 39 | /// Whether this imagery is an overlay. Not used currently. 40 | final bool overlay; 41 | 42 | /// Create a new instance of imagery. 43 | const Imagery({ 44 | required this.id, 45 | this.category, 46 | this.name, 47 | this.icon, 48 | this.attribution, 49 | this.best = false, 50 | this.overlay = false, 51 | }); 52 | 53 | /// Initialize layer state. May be useful when needed to make some async 54 | /// request, e.g. to download data from an URL. Executed by [imageryProvider] 55 | /// when the layer is chosen. 56 | Future initialize() async {} 57 | 58 | /// Builds the widgets to add to the [FlutterMap]. Note that this method 59 | /// is called on every widget rebuild, which can happen like 60 times a second. 60 | /// Do cache things. 61 | Widget buildLayer({bool reset = false}); 62 | 63 | @override 64 | String toString() => 'Imagery(id: $id, name: $name, category: $category)'; 65 | 66 | @override 67 | bool operator ==(Object other) => other is Imagery && other.id == id; 68 | 69 | @override 70 | int get hashCode => Object.hash(id, name); 71 | } 72 | -------------------------------------------------------------------------------- /lib/helpers/legend.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/multi_icon.dart'; 2 | import 'package:every_door_plugin/models/amenity.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class LegendItem { 6 | final Color? color; 7 | final MultiIcon? icon; 8 | final String label; 9 | 10 | LegendItem({this.color, this.icon, required this.label}); 11 | LegendItem.other(this.label) 12 | : color = kLegendOtherColor, 13 | icon = null; 14 | 15 | @override 16 | String toString() => 'LegendItem($color, $icon, "$label")'; 17 | 18 | bool get isOther => color == kLegendOtherColor; 19 | } 20 | 21 | const kLegendOtherColor = Colors.black; 22 | const kLegendNoColor = Colors.transparent; 23 | 24 | class NamedColor extends Color { 25 | final String name; 26 | const NamedColor(this.name, super.value); 27 | } 28 | 29 | class PresetLabel { 30 | final String id; 31 | final String label; 32 | 33 | const PresetLabel(this.id, this.label); 34 | 35 | @override 36 | bool operator ==(Object other) => 37 | other is PresetLabel && other.label == label && other.id == id; 38 | 39 | @override 40 | int get hashCode => Object.hash(id, label); 41 | } 42 | 43 | class LegendController extends ChangeNotifier { 44 | /// If false, does not add presets with icons defined to the legend. See 45 | /// [fixPreset] for adding icons. 46 | bool iconsInLegend = true; 47 | 48 | static const kLegendColors = [ 49 | NamedColor('red', 0xfffd0f0b), 50 | NamedColor('teal', 0xff1dd798), 51 | NamedColor('yellow', 0xfffbc74e), 52 | NamedColor('magenta', 0xfff807e7), 53 | NamedColor('olive', 0xffc5bb0c), 54 | NamedColor('green', 0xffb9fb77), 55 | NamedColor('pink', 0xfff76492), 56 | NamedColor('cyan', 0xff15f5ed), 57 | NamedColor('purple', 0xffab3ded), 58 | NamedColor('orange', 0xfffd7d0b), 59 | NamedColor('darkblue', 0xff4e5aef), // needs to be all lowercase 60 | NamedColor('brown', 0xff9b7716), 61 | ]; 62 | 63 | void fixPreset(String preset, {Color? color, MultiIcon? icon}) { 64 | } 65 | 66 | void resetFixes() { 67 | } 68 | 69 | /// Updates legend colors for [amenities]. The list should be ordered 70 | /// closest to farthest. The function tries to reuse colors. 71 | /// The [locale] is needed to translate labels. 72 | Future updateLegend(List amenities, 73 | {Locale? locale, int maxItems = 6}) async { 74 | } 75 | 76 | List get legend => const []; 77 | 78 | LegendItem? getLegendItem(OsmChange amenity) => null; 79 | } 80 | -------------------------------------------------------------------------------- /lib/helpers/draw_style.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class DrawingStyle { 4 | final Color color; 5 | final bool thin; 6 | final bool dashed; 7 | 8 | static const kDefaultStroke = 8.0; 9 | 10 | const DrawingStyle({ 11 | required this.color, 12 | this.thin = false, 13 | this.dashed = false, 14 | }); 15 | 16 | double get stroke => thin ? kDefaultStroke / 2.0 : kDefaultStroke; 17 | 18 | Color get casing { 19 | return color.computeLuminance() > 0.4 ? Colors.black : Colors.white; 20 | } 21 | 22 | @override 23 | bool operator ==(Object other) { 24 | if (other is! DrawingStyle) return false; 25 | return color == other.color && 26 | stroke < kDefaultStroke == other.stroke < kDefaultStroke && 27 | dashed == other.dashed; 28 | } 29 | 30 | @override 31 | int get hashCode => Object.hash(color, stroke, dashed); 32 | } 33 | 34 | const kTypeStyles = { 35 | "scribble": DrawingStyle(color: Colors.white, thin: true), 36 | "eraser": DrawingStyle(color: Colors.black54), 37 | "road": DrawingStyle(color: Colors.white70), 38 | "track": DrawingStyle(color: Colors.white70, dashed: true), 39 | "footway": DrawingStyle(color: Colors.red), 40 | "path": DrawingStyle(color: Colors.red, dashed: true), 41 | "cycleway": DrawingStyle(color: Colors.purpleAccent), 42 | "cycleway_shared": DrawingStyle(color: Colors.purpleAccent, dashed: true), 43 | "wall": DrawingStyle(color: Colors.yellow, thin: true), 44 | "fence": DrawingStyle(color: Colors.yellow, dashed: true, thin: true), 45 | "power": DrawingStyle(color: Colors.orangeAccent, thin: true), 46 | "stream": DrawingStyle(color: Colors.lightBlue), 47 | "culvert": DrawingStyle(color: Colors.lightBlue, dashed: true), 48 | }; 49 | 50 | final kTypeStylesReversed = 51 | kTypeStyles.map((key, value) => MapEntry(value, key)); 52 | 53 | const kUnknownStyle = DrawingStyle(color: Colors.grey); 54 | const kToolEraser = "eraser"; 55 | const kToolScribble = "scribble"; 56 | 57 | const kStyleIcons = { 58 | "eraser": Icons.clear, 59 | "scribble": Icons.draw, 60 | "road": Icons.edit_road, 61 | "track": Icons.forest, 62 | "footway": Icons.directions_walk, 63 | "path": Icons.directions_walk, 64 | "cycleway": Icons.directions_bike, 65 | "cycleway_shared": Icons.directions_bike, 66 | "wall": Icons.fence, 67 | "fence": Icons.fence, 68 | "power": Icons.power_input, 69 | "stream": Icons.water, 70 | "culvert": Icons.water, 71 | }; 72 | 73 | const kUnknownStyleIcon = Icons.line_axis; 74 | -------------------------------------------------------------------------------- /lib/helpers/tags/main_key.dart: -------------------------------------------------------------------------------- 1 | /// List of keys to consider when looking for a single main tag, in order of preference. 2 | const kMainKeys = [ 3 | 'amenity', 'shop', 'craft', 'tourism', 'historic', 'club', 4 | 'office', 'healthcare', 'leisure', 'emergency', 'attraction', 5 | 'xmas:feature', 6 | // non-amenity keys: 7 | 'highway', 'railway', 'natural', 8 | 'waterway', 'man_made', 'power', 'aeroway', 'aerialway', 9 | 'marker', 'public_transport', 'traffic_sign', 'hazard', 'telecom', 10 | 'advertising', 'playground', 'traffic_calming', 'cemetery', 11 | 'military', 'barrier', 12 | // structure tags should be last: 13 | 'building', 'entrance', 'building:part', 'indoor', 'boundary', 'landuse', 14 | ]; 15 | 16 | const kAmenityMainKeys = { 17 | 'amenity', 18 | 'shop', 19 | 'craft', 20 | 'tourism', 21 | 'historic', 22 | 'club', 23 | 'office', 24 | 'healthcare', 25 | 'leisure', 26 | 'emergency', 27 | 'attraction', 28 | }; 29 | 30 | const kDisused = 'disused:'; 31 | const kDeleted = 'was:'; 32 | const kBuildingDeleted = 'demolished:'; 33 | 34 | const _kLifecyclePrefixes = { 35 | 'proposed', 36 | 'planned', 37 | 'construction', 38 | 'disused', 39 | 'abandoned', 40 | 'ruins', 41 | 'demolished', 42 | 'removed', 43 | 'razed', 44 | 'destroyed', 45 | 'was', 46 | 'closed', 47 | 'historic', 48 | }; 49 | 50 | /// Find the single main key for an object. Also considers lifecycle prefixes. 51 | String? getMainKey(Map tags) { 52 | String? prefixed; 53 | bool isPrefixedAmenity = false; 54 | final prefixedKeys = Map.fromEntries(tags.keys 55 | .where((k) => k.contains(':')) 56 | .map((k) => MapEntry(clearPrefix(k), k))); 57 | for (final k in kMainKeys) { 58 | if (tags[k] == 'no') continue; 59 | if (tags.containsKey(k)) { 60 | // If we have seen a prefixed amenity, return that amenity instead of this non-amenity. 61 | if (!kAmenityMainKeys.contains(k) && isPrefixedAmenity) return prefixed; 62 | // Otherwise this amenity key takes precedence. 63 | return k; 64 | } 65 | if (prefixed == null && prefixedKeys.containsKey(k)) { 66 | prefixed = prefixedKeys[k]; 67 | if (tags[prefixed] == 'no') continue; 68 | isPrefixedAmenity = kAmenityMainKeys.contains(k); 69 | } 70 | } 71 | return prefixed; 72 | } 73 | 74 | /// Remove a lifecycle prefix for the key, which is before the first `:` character. 75 | String clearPrefix(String key) { 76 | final int pos = key.indexOf(':'); 77 | if (pos < 0) return key; 78 | return _kLifecyclePrefixes.contains(key.substring(0, pos)) 79 | ? key.substring(pos + 1) 80 | : key; 81 | } 82 | 83 | /// Remove a lifecycle prefix for the key, allowing for null input. See [clearPrefix]. 84 | String? clearPrefixNull(String? key) => key == null ? null : clearPrefix(key); 85 | -------------------------------------------------------------------------------- /lib/models/plugin.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:every_door_plugin/helpers/multi_icon.dart'; 4 | import 'package:every_door_plugin/helpers/plugin_i18n.dart'; 5 | import 'package:every_door_plugin/models/version.dart'; 6 | import 'package:every_door_plugin/plugins/every_door_plugin.dart'; 7 | import 'package:flutter/material.dart'; 8 | 9 | final kApiVersion = PluginVersion('1.1'); 10 | 11 | /// Thrown only when loading a plugin. Prints the enclosed exception as well. 12 | class PluginLoadException implements Exception { 13 | final String message; 14 | final Exception? parent; 15 | 16 | PluginLoadException(this.message, [this.parent]); 17 | 18 | @override 19 | String toString() { 20 | return parent == null ? message : "$message: $parent"; 21 | } 22 | } 23 | 24 | /// Plugin metadata. Basically an identifier and a dictionary 25 | /// from the bundled yaml file. 26 | class PluginData { 27 | final String id; 28 | final Map data; 29 | final bool installed; 30 | final PluginVersion version; 31 | 32 | PluginData(this.id, this.data, {this.installed = true}) 33 | : version = PluginVersion(data['version']); 34 | 35 | String get name => data['name'] ?? id; 36 | String get description => data['description'] ?? ''; 37 | String? get author => data['author']; 38 | PluginVersionRange? get apiVersion => 39 | data.containsKey('api') ? PluginVersionRange(data['api']) : null; 40 | 41 | Uri? get url => 42 | data.containsKey('source') ? Uri.tryParse(data['source']) : null; 43 | Uri? get homepage => 44 | data.containsKey('homepage') ? Uri.tryParse(data['homepage']) : null; 45 | 46 | MultiIcon? get icon => null; 47 | 48 | @override 49 | bool operator ==(Object other) => other is PluginData && other.id == id; 50 | 51 | @override 52 | int get hashCode => id.hashCode; 53 | } 54 | 55 | /// Plugin metadata. Same as [PluginData], but with added service methods 56 | /// for retrieving localizations and assets. Data read from the plugin 57 | /// metadata is final, but the [active] flag can be changed in runtime. 58 | /// Same with [instance]: it is initialized when the plugin is made active, 59 | /// and reset when it is disabled. 60 | abstract class Plugin extends PluginData { 61 | bool active; 62 | EveryDoorPlugin? instance; 63 | final Directory directory; 64 | 65 | Plugin({ 66 | required String id, 67 | required Map data, 68 | required this.directory, 69 | }) : active = false, 70 | super(id, data); 71 | 72 | String? get intro => data['intro']; 73 | 74 | @override 75 | MultiIcon? get icon => 76 | data.containsKey('icon') ? loadIcon(data['icon']) : null; 77 | 78 | PluginLocalizationsBranch getLocalizationsBranch(String prefix); 79 | 80 | String translate( 81 | BuildContext context, 82 | String key, { 83 | Map? args, 84 | }); 85 | 86 | File resolvePath(String name); 87 | 88 | Directory resolveDirectory(String name); 89 | 90 | MultiIcon loadIcon(String name, [String? tooltip]); 91 | 92 | Future showIntro(BuildContext context) async {} 93 | } 94 | -------------------------------------------------------------------------------- /lib/plugins/interface.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/auth/controller.dart'; 2 | import 'package:every_door_plugin/helpers/auth/provider.dart'; 3 | import 'package:every_door_plugin/models/imagery.dart'; 4 | import 'package:every_door_plugin/models/plugin.dart'; 5 | import 'package:every_door_plugin/plugins/events.dart'; 6 | import 'package:every_door_plugin/plugins/ext_overlay.dart'; 7 | import 'package:every_door_plugin/plugins/preferences.dart'; 8 | import 'package:every_door_plugin/plugins/providers.dart'; 9 | import 'package:every_door_plugin/screens/modes/definitions/base.dart'; 10 | import 'package:logging/logging.dart'; 11 | 12 | /// This class is used by plugins to interact with the app. 13 | /// It might be rebuilt often, and contains references to Riverpod 14 | /// ref and BuildContext (if applicable). And also a ton of convenience 15 | /// methods. 16 | abstract class EveryDoorApp { 17 | Plugin get plugin; 18 | Function()? get onRepaint; 19 | 20 | PluginPreferences get preferences; 21 | PluginProviders get providers; 22 | PluginEvents get events; 23 | Logger get logger; 24 | 25 | // Future get database => _ref.read(pluginDatabaseProvider).database; 26 | 27 | /// When available, initiates the screen repaint. Useful for updating the 28 | /// plugin settings screen. 29 | void repaint(); 30 | 31 | /// Adds an overlay layer. You only need to specify the [Imagery.id] 32 | /// and [Imagery.buildLayer], but also set the [Imagery.overlay] to true. 33 | /// For plugins, it would make sense to either use the metadata static file, 34 | /// or to instantiate [ExtOverlay]. 35 | /// 36 | /// Unlike the specific mode-bound overlays, those appear everywhere, even 37 | /// in map-opening fields. If you want to add an overlay just to the main 38 | /// map, see [PluginEvents.onModeCreated] and [BaseModeDefinition.addOverlay]. 39 | void addOverlay(Imagery imagery) { 40 | if (!imagery.overlay) { 41 | throw ArgumentError("Imagery should be an overlay"); 42 | } 43 | } 44 | 45 | /// Adds an editor mode. Cannot replace existing ones, use [removeMode] 46 | /// for that. 47 | void addMode(BaseModeDefinition mode) { 48 | } 49 | 50 | /// Removes the mode. Can remove both a pre-defined mode (like "notes"), 51 | /// and a plugin-added one. 52 | void removeMode(String name) { 53 | } 54 | 55 | /// Do something with every mode installed. Useful for dynamically adding 56 | /// and removing buttons and layers, for example. 57 | void eachMode(Function(BaseModeDefinition) callback) { 58 | } 59 | 60 | /// Adds an authentication provider. It is not currently possible 61 | /// to override an [AuthController]. It is also not possible to 62 | /// replace the generic providers such as "osm", or use providers 63 | /// defined in other plugins (because of the mandatory prefix). 64 | void addAuthProvider(String name, AuthProvider provider) { 65 | if (provider.title == null) { 66 | throw ArgumentError("Title is required for a provider"); 67 | } 68 | } 69 | 70 | /// Returns a controller for an authentication provider. Use "osm" 71 | /// to get OSM request headers. 72 | AuthController auth(String name); 73 | } 74 | -------------------------------------------------------------------------------- /lib/models/version.dart: -------------------------------------------------------------------------------- 1 | class PluginVersion { 2 | late final int? _major; 3 | late final int _minor; 4 | 5 | static final zero = PluginVersion('0'); 6 | 7 | /// Constructs a version instance. Possible types for the [version] are: 8 | /// 9 | /// * [int] - depending on [flatNumbering], parsed as "version" or "version.0" 10 | /// * [double] or [String] - if there's a point, parsed as "major.minor", 11 | /// otherwise depends on [flatNumbering] (see [int]). 12 | /// * [null] - flat version 0. 13 | PluginVersion(dynamic version, [bool flatNumbering = true]) { 14 | if (version == null) { 15 | // Null version is considered "0", equal to [zero]. 16 | _major = null; 17 | _minor = 0; 18 | } else if (version is int) { 19 | _major = flatNumbering ? null : version; 20 | _minor = flatNumbering ? version : 0; 21 | } else if (version is String || version is double) { 22 | final vs = version.toString(); 23 | final p = vs.indexOf('.'); 24 | if (p < 0) { 25 | final v = int.parse(vs); 26 | _major = flatNumbering ? null : v; 27 | _minor = flatNumbering ? v : 0; 28 | } else { 29 | _major = int.parse(vs.substring(0, p)); 30 | _minor = int.parse(vs.substring(p + 1)); 31 | } 32 | } else { 33 | throw ArgumentError('Plugin version should be a number or a string'); 34 | } 35 | } 36 | 37 | PluginVersion.exact(this._major, this._minor); 38 | 39 | @override 40 | String toString() => _major == null ? _minor.toString() : '$_major.$_minor'; 41 | 42 | @override 43 | bool operator ==(Object other) => 44 | other is PluginVersion && 45 | other._major == _major && 46 | other._minor == _minor; 47 | 48 | bool operator <(PluginVersion other) { 49 | if (_major == null) return other._major != null || other._minor > _minor; 50 | if (other._major == null || other._major < _major) return false; 51 | return other._major > _major || other._minor > _minor; 52 | } 53 | 54 | bool operator >(PluginVersion other) { 55 | if (_major != null) 56 | return other._major == null || 57 | other._major < _major || 58 | (other._major == _major && other._minor < _minor); 59 | return other._major == null && other._minor < _minor; 60 | } 61 | 62 | bool operator <=(PluginVersion other) => other == this || this < other; 63 | 64 | bool fresherThan(PluginVersion? version) => version == null || this > version; 65 | 66 | PluginVersion nextMajor() => PluginVersion.exact((_major ?? 0) + 1, 0); 67 | 68 | @override 69 | int get hashCode => Object.hash(_major, _minor); 70 | } 71 | 72 | class PluginVersionRange { 73 | late final PluginVersion min; 74 | late final PluginVersion max; 75 | 76 | PluginVersionRange(dynamic data) { 77 | if (data is String || data is num) { 78 | min = PluginVersion(data, false); 79 | max = min.nextMajor(); 80 | } else if (data is Iterable && data.length == 2) { 81 | final List versions = data.toList(); 82 | min = PluginVersion(versions[0], false); 83 | max = PluginVersion(versions[1], false); 84 | } 85 | } 86 | 87 | bool matches(PluginVersion version) => min <= version && version < max; 88 | 89 | @override 90 | String toString() => '[$min, $max)'; 91 | } 92 | -------------------------------------------------------------------------------- /lib/widgets/map_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/multi_icon.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class OverlayButtonWidget extends StatelessWidget { 5 | /// Padding for the button. 6 | final EdgeInsets? padding; 7 | 8 | /// To which corner of the map should the button be aligned. 9 | final Alignment alignment; 10 | 11 | /// Function to call when the button is pressed. 12 | final void Function(BuildContext) onPressed; 13 | 14 | /// Function to call on long tap. 15 | final void Function(BuildContext)? onLongPressed; 16 | 17 | /// Icon to display. 18 | final IconData icon; 19 | 20 | /// Set to false to hide the button. 21 | final bool enabled; 22 | 23 | /// Tooltip and semantics message. 24 | final String? tooltip; 25 | 26 | /// Add safe area to the bottom padding. Enable when the map is full-screen. 27 | final bool safeBottom; 28 | 29 | /// Add safe area to the right side padding. 30 | final bool safeRight; 31 | 32 | const OverlayButtonWidget({ 33 | super.key, 34 | required this.alignment, 35 | this.padding, 36 | required this.onPressed, 37 | this.onLongPressed, 38 | required this.icon, 39 | this.enabled = true, 40 | this.tooltip, 41 | this.safeBottom = false, 42 | this.safeRight = false, 43 | }); 44 | 45 | @override 46 | Widget build(BuildContext context) => Container(); 47 | } 48 | 49 | class MapButtonColumn extends StatelessWidget { 50 | /// Padding for the button. 51 | final EdgeInsets? padding; 52 | 53 | /// To which corner of the map should the button be aligned. 54 | final Alignment alignment; 55 | 56 | /// Add safe area to the bottom padding. Enable when the map is full-screen. 57 | final bool safeBottom; 58 | 59 | /// Add safe area to the right side padding. 60 | final bool safeRight; 61 | 62 | /// Enclosed button. 63 | final List buttons; 64 | 65 | const MapButtonColumn({ 66 | super.key, 67 | required this.buttons, 68 | required this.alignment, 69 | this.padding, 70 | this.safeBottom = false, 71 | this.safeRight = false, 72 | }); 73 | 74 | @override 75 | Widget build(BuildContext context) { 76 | return Container(); 77 | } 78 | } 79 | 80 | class MapButton extends StatelessWidget { 81 | /// An optional identifier to refer this button later. 82 | final String? id; 83 | 84 | /// Function to call when the button is pressed. 85 | final void Function(BuildContext) onPressed; 86 | 87 | /// Function to call on long tap. 88 | final void Function(BuildContext)? onLongPressed; 89 | 90 | /// Icon to display. 91 | final MultiIcon? icon; 92 | 93 | /// Widget to display when there's no icon. 94 | final Widget? child; 95 | 96 | /// Set to false to hide the button. 97 | final bool enabled; 98 | 99 | /// Tooltip and semantics message. 100 | final String? tooltip; 101 | 102 | const MapButton({ 103 | super.key, 104 | this.id, 105 | required this.onPressed, 106 | this.onLongPressed, 107 | this.icon, 108 | this.child, 109 | this.enabled = true, 110 | this.tooltip, 111 | }) : assert(icon != null || child != null); 112 | 113 | @override 114 | Widget build(BuildContext context) { 115 | return Container(); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /lib/helpers/auth/provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/multi_icon.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// Authentication token class. Should be subclasses to contain actual 5 | /// token data. It's a good idea to add a factory constructor 6 | /// [AuthToken.fromJson] to keep serialization and deserialization in one place. 7 | abstract class AuthToken { 8 | const AuthToken(); 9 | 10 | /// Serialize token contents into a json, to store on the device. 11 | Map toJson(); 12 | 13 | /// Checks whether the token is valid. Should return false if anything 14 | /// in the token data prompts it won't work. 15 | bool isValid() => true; 16 | 17 | /// Check whether the token is obsolete. If the token has an expiration 18 | /// date, override this method. 19 | bool needsRefresh() => false; 20 | } 21 | 22 | /// A base class for user details. Override to add more, e.g. an avatar. 23 | class UserDetails { 24 | final String displayName; 25 | const UserDetails({required this.displayName}); 26 | } 27 | 28 | /// An exception thrown when the authentication goes wrong. 29 | /// Please do not forget to provide a message. 30 | class AuthException implements Exception { 31 | final String message; 32 | 33 | AuthException(this.message); 34 | 35 | @override 36 | String toString() => 'AuthException($message)'; 37 | } 38 | 39 | /// Authentication provider base class. Should know how to login and 40 | /// to get user details. Also stores an [endpoint] for making calls. 41 | abstract class AuthProvider { 42 | /// A constant constructor doing nothing. A provider should not have a state. 43 | const AuthProvider(); 44 | 45 | /// Service endpoint to make requests. 46 | String get endpoint; 47 | 48 | /// A title for the settings panel. 49 | String? get title => null; 50 | 51 | /// An icon for the settings panel. 52 | MultiIcon? get icon => null; 53 | 54 | /// Unpack token retrieved from a secure storage. 55 | AuthToken tokenFromJson(Map data); 56 | 57 | /// Open a login panel, perform the authentication, and receive 58 | /// a token. 59 | /// Should return [null] if the process was manually cancelled, 60 | /// or throw an [AuthException] if it failed. 61 | Future login(BuildContext context); 62 | 63 | /// In case a token can become obsolete, implement this method. 64 | Future refreshToken(AuthToken token) async { 65 | throw AuthException("Tokens cannot be refreshed"); 66 | } 67 | 68 | /// If needed, inform the server to log the user out. 69 | Future logout(AuthToken token) async {} 70 | 71 | /// Returns headers to be added to an API request. 72 | /// Usually this adds a single "Authentication" header, 73 | /// but this depends on the API. 74 | /// 75 | /// See also [getApiKey], one of those should be implemented. 76 | Map getHeaders(AuthToken token) { 77 | throw AuthException("Headers cannot be built"); 78 | } 79 | 80 | /// Returns a string to be supplied to API, if it needs one. 81 | /// 82 | /// See also [getHeaders], one of those should be implemented. 83 | String getApiKey(AuthToken token) { 84 | throw AuthException("API key cannot be generated"); 85 | } 86 | 87 | /// Makes a query to the server asking for user details. 88 | /// It gets called when opening the app, and after logging in. 89 | /// 90 | /// If the request fails, throw an [AuthException]. 91 | Future loadUserDetails(AuthToken token); 92 | 93 | /// Test the auth credentials. Should return [true] if they work. 94 | Future testHeaders(Map? headers, String? apiKey); 95 | } 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The [Every Door](https://every-door.app/) OpenStreetMap editor supports plugins. 2 | Those can be written as static files, or with Dart and Flutter code. This package 3 | simplifies creation of a plugin (either kind), and provides models and bindings 4 | for the development. 5 | 6 | ## Creating a static plugin 7 | 8 | With this package, it's easy: it provides a script that can be executed from anywhere. 9 | Install it with: 10 | 11 | dart pub global activate every_door_plugin 12 | 13 | The proper way would be to create a directory for a plugin, and inside it, a `plugin` 14 | directory with all the files, including `plugin.yaml`. When you run `edp` 15 | (or `dart pub global run every_door_plugin` if that doesn't work), it would create 16 | a `dist` subdirectory, in which it would put a packaged plugin. 17 | 18 | Obviously for a static plugin, you can just use whatever archiving option you've got: 19 | [edp files are just zip archives](https://every-door.app/plugins/metadata/). 20 | 21 | ## Creating a plugin with code 22 | 23 | First, create a Flutter package with its generator or with Android Studio — whatever 24 | works for you. Name it as your plugin: the title should start with a latin letter and 25 | contain, besides those, only numbers, dashes, and underscores. 26 | 27 | Alternatively just create a directory. For code, put this into `pubspec.yaml`: 28 | 29 | ```yaml 30 | name: plugin_id 31 | description: "Plugin Name" 32 | version: 0.1.0 33 | 34 | environment: 35 | sdk: ^3.6.0 36 | flutter: "^3.35.0" 37 | 38 | dependencies: 39 | flutter: 40 | sdk: flutter 41 | every_door_plugin: ^1.0.0 42 | ``` 43 | 44 | Add `every_door_plugin: 1.0.0` to the dependencies in `pubspec.yaml`. Also mind that those 45 | keys will be copied to the plugin metadata: 46 | 47 | * `name` → `id` 48 | * `description` → `name` (don't write "every door plugin" or anything like there) 49 | * `homepage` → `homepage` 50 | * `version` → `version` 51 | 52 | Note that while version there follows semantic versioning, 53 | only the first two numbers will be used for the plugin version (e.g. for `0.3.1` 54 | the version would be `0.3`, so there is no point in using patch versions). 55 | 56 | You can also add an `every_door` section and straight write 57 | [`plugin.yaml`](https://every-door.app/plugins/metadata/) contents there. 58 | The pubspec top values still have the priority. 59 | 60 | Create a `plugin` directory for any static files you will need packaged. 61 | When you refer a file like `icons/bus.svg`, whether from the yaml file 62 | or from the code, it will be expected in `plugin/icons/bus.svg`. 63 | 64 | The code goes into the `lib` directory, with the `lib/main.dart` for the main code. 65 | It can include other dart files from the same directory or sub-directories. 66 | 67 | ## Building a plugin 68 | 69 | Having added this package as a dependency, type this in the console (e.g. in Android Studio 70 | terminal): 71 | 72 | flutter pub get 73 | dart run every_door_plugin 74 | 75 | It will compile the code and create an edp file in the `dist` subdirectory with the 76 | plugin id and version for the file name: `plugin_id_1.0.edp`. Transfer it to your phone 77 | to test it, and upload to [the repository](https://plugins.every-door.app/) when finished. 78 | 79 | ## Author and License 80 | 81 | Written by Ilya Zverev, published under the ISC license. 82 | 83 | The author is sponsored by many individual contributors through [GitHub](https://github.com/sponsors/Zverik) 84 | and [Liberapay](https://liberapay.com/zverik). Thank you everybody! 85 | 86 | The NLNet Foundation is [sponsoring](https://nlnet.nl/project/EveryDoor/) the development in 2025 87 | through the [NGI Commons Fund](https://nlnet.nl/commonsfund) with funds from the European Commission. 88 | 89 | Want to sponsor the development? [Contact Ilya](mailto:ilya@zverev.info) directly or through 90 | [his company](https://avatudkaart.ee/). 91 | -------------------------------------------------------------------------------- /lib/helpers/geometry/geometry.dart: -------------------------------------------------------------------------------- 1 | import 'package:latlong2/latlong.dart' show LatLng; 2 | import 'package:flutter_map/flutter_map.dart' show LatLngBounds; 3 | 4 | class GeometryException implements Exception { 5 | final String message; 6 | 7 | const GeometryException(this.message); 8 | } 9 | 10 | abstract class Geometry { 11 | LatLngBounds get bounds; 12 | LatLng get center; 13 | } 14 | 15 | class Polygon extends Geometry { 16 | final List _nodes; 17 | 18 | Polygon(Iterable nodes) : _nodes = List.of(nodes) { 19 | if (_nodes.isNotEmpty && _nodes.last == _nodes.first) _nodes.removeLast(); 20 | if (_nodes.length < 3) 21 | throw GeometryException('A polygon must have at least three nodes.'); 22 | } 23 | 24 | @override 25 | LatLngBounds get bounds => LatLngBounds.fromPoints(_nodes); 26 | 27 | @override 28 | LatLng get center => bounds.center; 29 | 30 | bool contains(LatLng point) => false; 31 | 32 | bool containsPolygon(Polygon poly) { 33 | if (!bounds.containsBounds(poly.bounds)) return false; 34 | for (final p in poly._nodes) if (!contains(p)) return false; 35 | // TODO: check that vertices do not intersect. 36 | return true; 37 | } 38 | 39 | LatLng findPointOnSurface() => center; 40 | 41 | @override 42 | String toString() => 'Polygon($_nodes)'; 43 | } 44 | 45 | class Envelope implements Polygon { 46 | final LatLngBounds _bounds; 47 | 48 | const Envelope(this._bounds); 49 | 50 | @override 51 | List get _nodes => throw UnimplementedError(); 52 | 53 | @override 54 | LatLngBounds get bounds => _bounds; 55 | 56 | @override 57 | LatLng get center => LatLng( 58 | (bounds.south + bounds.north) / 2, (bounds.west + bounds.east) / 2); 59 | 60 | @override 61 | bool contains(LatLng point) => _bounds.contains(point); 62 | 63 | @override 64 | bool containsPolygon(Polygon poly) => _bounds.containsBounds(poly.bounds); 65 | 66 | @override 67 | LatLng findPointOnSurface() => center; 68 | 69 | @override 70 | String toString() => 'Envelope(${_bounds.southWest}, ${_bounds.northEast})'; 71 | } 72 | 73 | class MultiPolygon implements Polygon { 74 | final List outer = []; 75 | final List inner = []; 76 | 77 | MultiPolygon(Iterable polygons) { 78 | // TODO: sort 79 | outer.addAll(polygons); 80 | } 81 | 82 | @override 83 | LatLngBounds get bounds => LatLngBounds.fromPoints([ 84 | for (final p in outer) ...[p.bounds.northWest, p.bounds.southEast] 85 | ]); 86 | 87 | @override 88 | LatLng get center => LatLng( 89 | (bounds.south + bounds.north) / 2, (bounds.west + bounds.east) / 2); 90 | 91 | @override 92 | bool contains(LatLng point) { 93 | return outer.any((p) => p.contains(point)) && 94 | !inner.any((p) => p.contains(point)); 95 | } 96 | 97 | @override 98 | bool containsPolygon(Polygon poly) { 99 | if (!outer.any((element) => element.containsPolygon(poly))) return false; 100 | // Welp, not going to do a proper implementation 101 | throw UnimplementedError(); 102 | } 103 | 104 | @override 105 | String toString() => 106 | 'MultiPolygon(${outer.length} outer, ${inner.length} inner)'; 107 | 108 | @override 109 | List get _nodes => throw UnimplementedError(); 110 | 111 | @override 112 | LatLng findPointOnSurface() => center; 113 | } 114 | 115 | class LineString extends Geometry { 116 | final List nodes; 117 | LatLngBounds? _cachedBounds; 118 | 119 | LineString(Iterable nodes) : nodes = List.of(nodes, growable: false) { 120 | if (this.nodes.length < 2) 121 | throw GeometryException('A path must have at least two nodes.'); 122 | } 123 | 124 | @override 125 | LatLngBounds get bounds { 126 | _cachedBounds ??= LatLngBounds.fromPoints(nodes); 127 | return _cachedBounds!; 128 | } 129 | 130 | @override 131 | LatLng get center => bounds.center; 132 | 133 | double getLengthInMeters() => 0; 134 | 135 | LatLng closestPoint(LatLng point) => point; 136 | 137 | double distanceToPoint(LatLng point, {bool inMeters = true}) => 0; 138 | 139 | bool intersects(LineString other) => false; 140 | 141 | @override 142 | String toString() => 'LineString($nodes)'; 143 | } 144 | -------------------------------------------------------------------------------- /lib/plugins/bindings/plugins/providers.eval.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers 2 | import 'package:dart_eval/dart_eval_bridge.dart'; 3 | import 'package:every_door_plugin/plugins/providers.dart'; 4 | import 'package:dart_eval/stdlib/core.dart'; 5 | import 'package:flutter_map_eval/latlong2/latlong2_eval.dart'; 6 | 7 | /// dart_eval wrapper binding for [PluginProviders] 8 | class $PluginProviders implements $Instance { 9 | /// Configure this class for use in a [Runtime] 10 | static void configureForRuntime(Runtime runtime) { 11 | } 12 | 13 | /// Compile-time type specification of [$PluginProviders] 14 | static const $spec = BridgeTypeSpec( 15 | 'package:every_door/plugins/providers.dart', 16 | 'PluginProviders', 17 | ); 18 | 19 | /// Compile-time type declaration of [$PluginProviders] 20 | static const $type = BridgeTypeRef($spec); 21 | 22 | /// Compile-time class declaration of [$PluginProviders] 23 | static const $declaration = BridgeClassDef( 24 | BridgeClassType($type), 25 | constructors: { 26 | }, 27 | 28 | methods: {}, 29 | getters: { 30 | 'location': BridgeMethodDef( 31 | BridgeFunctionDef( 32 | returns: BridgeTypeAnnotation( 33 | BridgeTypeRef( 34 | BridgeTypeSpec('package:latlong2/latlong.dart', 'LatLng'), 35 | [], 36 | ), 37 | ), 38 | namedParams: [], 39 | params: [], 40 | ), 41 | ), 42 | 43 | 'isTracking': BridgeMethodDef( 44 | BridgeFunctionDef( 45 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 46 | namedParams: [], 47 | params: [], 48 | ), 49 | ), 50 | 51 | 'compass': BridgeMethodDef( 52 | BridgeFunctionDef( 53 | returns: BridgeTypeAnnotation( 54 | BridgeTypeRef(CoreTypes.double, []), 55 | nullable: true, 56 | ), 57 | namedParams: [], 58 | params: [], 59 | ), 60 | ), 61 | }, 62 | setters: { 63 | 'location': BridgeMethodDef( 64 | BridgeFunctionDef( 65 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 66 | namedParams: [], 67 | params: [ 68 | BridgeParameter( 69 | 'value', 70 | BridgeTypeAnnotation( 71 | BridgeTypeRef( 72 | BridgeTypeSpec('package:latlong2/latlong.dart', 'LatLng'), 73 | [], 74 | ), 75 | ), 76 | false, 77 | ), 78 | ], 79 | ), 80 | ), 81 | 82 | 'zoom': BridgeMethodDef( 83 | BridgeFunctionDef( 84 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 85 | namedParams: [], 86 | params: [ 87 | BridgeParameter( 88 | 'value', 89 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.double, [])), 90 | false, 91 | ), 92 | ], 93 | ), 94 | ), 95 | }, 96 | fields: {}, 97 | wrap: true, 98 | bridge: false, 99 | ); 100 | 101 | final $Instance _superclass; 102 | 103 | @override 104 | final PluginProviders $value; 105 | 106 | @override 107 | PluginProviders get $reified => $value; 108 | 109 | /// Wrap a [PluginProviders] in a [$PluginProviders] 110 | $PluginProviders.wrap(this.$value) : _superclass = $Object($value); 111 | 112 | @override 113 | int $getRuntimeType(Runtime runtime) => runtime.lookupType($spec); 114 | 115 | @override 116 | $Value? $getProperty(Runtime runtime, String identifier) { 117 | switch (identifier) { 118 | case 'location': 119 | final _location = $value.location; 120 | return $LatLng.wrap(_location); 121 | 122 | case 'isTracking': 123 | final _isTracking = $value.isTracking; 124 | return $bool(_isTracking); 125 | 126 | case 'compass': 127 | final _compass = $value.compass; 128 | return _compass == null ? const $null() : $double(_compass); 129 | } 130 | return _superclass.$getProperty(runtime, identifier); 131 | } 132 | 133 | @override 134 | void $setProperty(Runtime runtime, String identifier, $Value value) { 135 | switch (identifier) { 136 | case 'location': 137 | $value.location = value.$value; 138 | return; 139 | 140 | case 'zoom': 141 | $value.zoom = value.$value; 142 | return; 143 | } 144 | return _superclass.$setProperty(runtime, identifier, value); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /lib/helpers/tags/element_kind.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/tags/element_kind_std.dart'; 2 | import 'package:every_door_plugin/helpers/tags/main_key.dart'; 3 | import 'package:every_door_plugin/helpers/multi_icon.dart'; 4 | import 'package:every_door_plugin/helpers/tags/tag_matcher.dart'; 5 | import 'package:every_door_plugin/models/amenity.dart'; 6 | 7 | /// A static factory for [ElementKindImpl], which also contains some 8 | /// pre-defined kinds and supports merging kinds. 9 | class ElementKind { 10 | /// Matches objects without meaningful tags. 11 | static ElementKindImpl get empty => _kinds["empty"]!; 12 | 13 | /// Matches everything. Is returned by [match] and [matchChange] 14 | /// when no other match was found. 15 | static ElementKindImpl get unknown => _kinds["unknown"]!; 16 | 17 | /// Matches amenities like restaurants. 18 | static ElementKindImpl get amenity => _kinds['amenity']!; 19 | 20 | /// Matches micromapping-related objects like trees. 21 | static ElementKindImpl get micro => _kinds["micro"]!; 22 | 23 | /// Matches buildings, even when there are other tags. 24 | static ElementKindImpl get building => _kinds["building"]!; 25 | 26 | /// Matches entrances, even when there are other tags. 27 | static ElementKindImpl get entrance => _kinds["entrance"]!; 28 | 29 | /// Matches address points that don't have other more important uses. 30 | static ElementKindImpl get address => _kinds["address"]!; 31 | 32 | /// Matches long-standing amenities that are not supposed 33 | /// to disappear overnight. 34 | static ElementKindImpl get structure => _kinds["structure"]!; 35 | 36 | /// Matches objects that would benefit from "check_date" tag. 37 | /// Defaults to [amenity]. 38 | static ElementKindImpl get needsCheck => _kinds["needsCheck"]!; 39 | 40 | /// Matches micromapping-related objects that miss some important 41 | /// secondary tags. 42 | static ElementKindImpl get needsInfo => _kinds["needsInfo"]!; 43 | 44 | /// Matches everything the editor processes (not everything ever 45 | /// like [unknown]). 46 | static ElementKindImpl get everything => _kinds["everything"]!; 47 | 48 | static final Map _kinds = {}; 49 | 50 | ElementKind._(); 51 | 52 | static ElementKindImpl get(String name) => _kinds[name] ?? unknown; 53 | 54 | static const _kMatchedKinds = [ 55 | 'amenity', 56 | 'micro', 57 | 'building', 58 | 'entrance', 59 | 'address', 60 | 'empty', 61 | ]; 62 | 63 | static ElementKindImpl match(Map tags, 64 | [List? kinds]) { 65 | for (final k in kinds ?? _kMatchedKinds) { 66 | final ek = _kinds[k]!; 67 | if (ek.matchesTags(tags)) return ek; 68 | } 69 | return ElementKind.unknown; 70 | } 71 | 72 | static ElementKindImpl matchChange(OsmChange change, 73 | [List? kinds]) { 74 | kinds ??= _kMatchedKinds.map((k) => _kinds[k]!).toList(); 75 | for (final k in kinds) { 76 | if (k.matchesChange(change)) return k; 77 | } 78 | return ElementKind.unknown; 79 | } 80 | 81 | static void reset() { 82 | register(ElementKindImpl(name: 'unknown')); // by default everything matches 83 | registerStandardKinds(); 84 | } 85 | 86 | static void register(ElementKindImpl kind) { 87 | final name = kind.name; 88 | if (!_kinds.containsKey(name)) { 89 | _kinds[name] = kind; 90 | } else { 91 | _kinds[name] = _kinds[name]!.mergeWith(kind); 92 | } 93 | } 94 | } 95 | 96 | class ElementKindImpl { 97 | final String name; 98 | final MultiIcon? icon; 99 | final TagMatcher? matcher; 100 | final bool onMainKey; 101 | final bool replace; 102 | 103 | const ElementKindImpl({ 104 | required this.name, 105 | this.matcher, 106 | this.icon, 107 | this.onMainKey = true, 108 | this.replace = true, 109 | }); 110 | 111 | bool matchesTags(Map tags) { 112 | String? mainKey; 113 | if (onMainKey) { 114 | mainKey = getMainKey(tags); 115 | if (mainKey == null) return false; 116 | } 117 | return matcher?.matches(tags, mainKey) ?? false; 118 | } 119 | 120 | bool matchesChange(OsmChange change) { 121 | String? mainKey; 122 | if (onMainKey) { 123 | mainKey = change.mainKey; 124 | if (mainKey == null) return false; 125 | } 126 | 127 | return matcher?.matchesChange(change, mainKey) ?? 128 | matchesTags(change.getFullTags()); 129 | } 130 | 131 | ElementKindImpl mergeWith(ElementKindImpl other) { 132 | return ElementKindImpl( 133 | name: name, 134 | icon: other.icon ?? icon, 135 | onMainKey: other.onMainKey, 136 | matcher: matcher == null || other.replace 137 | ? other.matcher 138 | : matcher!.mergeWith(other.matcher), 139 | ); 140 | } 141 | 142 | factory ElementKindImpl.fromJson(String name, Map data) { 143 | final replace = data.containsKey('matcher'); 144 | return ElementKindImpl( 145 | name: name, 146 | onMainKey: data['onMainKey'] as bool? ?? true, 147 | matcher: TagMatcher.fromJson(data[replace ? 'matcher' : 'update']), 148 | replace: replace, 149 | ); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /lib/models/osm_element.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/tags/element_kind.dart'; 2 | import 'package:every_door_plugin/helpers/geometry/geometry.dart'; 3 | import 'package:latlong2/latlong.dart' show LatLng; 4 | 5 | /// An element type: node, way, or relation. 6 | enum OsmElementType { node, way, relation } 7 | 8 | /// Mapping from the enum value to strings. 9 | const kOsmElementTypeName = { 10 | OsmElementType.node: 'node', 11 | OsmElementType.way: 'way', 12 | OsmElementType.relation: 'relation', 13 | }; 14 | 15 | /// OSM identifier: a type and a number. 16 | class OsmId { 17 | final OsmElementType type; 18 | final int ref; 19 | 20 | const OsmId(this.type, this.ref); 21 | 22 | /// Parses a string like "n123" into [OsmId] with the type from the letter 23 | /// (e.g. node for "n") and the number from the rest. 24 | factory OsmId.fromString(String s) { 25 | return OsmId(OsmElementType.node, int.parse(s.substring(1))); 26 | } 27 | 28 | /// Returns a representation like "node/123", to use in building 29 | /// website URLs. 30 | String get fullRef => '${kOsmElementTypeName[type]}/$ref'; 31 | 32 | /// Returns a string like "n123" for a node with id=123. Can be 33 | /// parsed back into an [OsmId] with [OsmId.fromString]. 34 | @override 35 | String toString() => ''; 36 | 37 | @override 38 | bool operator ==(Object other) => 39 | other is OsmId && type == other.type && ref == other.ref; 40 | 41 | @override 42 | int get hashCode => type.hashCode + ref.hashCode; 43 | } 44 | 45 | /// An OSM relation member. Contains of an OSM id and an optional [role]. 46 | class OsmMember { 47 | final OsmId id; 48 | final String? role; 49 | 50 | const OsmMember(this.id, [this.role]); 51 | 52 | OsmElementType get type => id.type; 53 | 54 | factory OsmMember.fromString(String s) { 55 | final idx = s.indexOf(' '); 56 | if (idx < 0) return OsmMember(OsmId.fromString(s)); 57 | return OsmMember( 58 | OsmId.fromString(s.substring(0, idx)), s.substring(idx + 1)); 59 | } 60 | 61 | @override 62 | String toString() { 63 | if (role == null) return id.toString(); 64 | return '$id $role'; 65 | } 66 | } 67 | 68 | /// Whether this object is a member of a way or a relation. Way 69 | /// membership takes precedence. 70 | enum IsMember { no, way, relation } 71 | 72 | /// An OSM element downloaded from the server. 73 | class OsmElement { 74 | final OsmId id; 75 | final Map tags; 76 | final int version; 77 | final DateTime timestamp; 78 | final DateTime? downloaded; 79 | final LatLng? center; 80 | final Geometry? geometry; 81 | final List? nodes; 82 | final Map? nodeLocations; // not stored to the database 83 | final List? members; 84 | final IsMember isMember; 85 | 86 | OsmElementType get type => id.type; 87 | 88 | OsmElement({ 89 | required this.id, 90 | required this.version, 91 | required this.timestamp, 92 | this.downloaded, 93 | required this.tags, 94 | LatLng? center, 95 | this.geometry, 96 | this.nodes, 97 | this.nodeLocations, 98 | this.members, 99 | this.isMember = IsMember.no, 100 | }) : center = center ?? 101 | (geometry is Polygon 102 | ? geometry.findPointOnSurface() 103 | : geometry?.center); 104 | 105 | OsmElement copyWith( 106 | {Map? tags, 107 | int? id, 108 | int? version, 109 | LatLng? center, 110 | Geometry? geometry, 111 | IsMember? isMember, 112 | List? nodes, 113 | Map? nodeLocations, 114 | bool currentTimestamp = false, 115 | bool clearMembers = false}) { 116 | return OsmElement( 117 | id: id != null ? OsmId(this.id.type, id) : this.id, 118 | version: version ?? this.version, 119 | timestamp: currentTimestamp ? DateTime.now().toUtc() : timestamp, 120 | downloaded: downloaded, 121 | tags: tags ?? this.tags, 122 | center: center ?? this.center, 123 | geometry: geometry ?? this.geometry, 124 | nodes: clearMembers ? null : (nodes ?? this.nodes), 125 | nodeLocations: clearMembers || (nodeLocations?.isEmpty ?? false) 126 | ? null 127 | : (nodeLocations ?? this.nodeLocations), 128 | members: clearMembers ? null : members, 129 | isMember: isMember ?? this.isMember, 130 | ); 131 | } 132 | 133 | /// Updates location and reference properties from `old` 134 | /// (When this element was downloaded fresh, but is missing some). 135 | OsmElement updateMeta(OsmElement? old) { 136 | if (old == null) return this; 137 | return OsmElement( 138 | id: id, 139 | version: version, 140 | timestamp: timestamp, 141 | downloaded: downloaded, 142 | tags: tags, 143 | center: center ?? old.center, 144 | geometry: geometry ?? old.geometry, 145 | nodes: nodes ?? old.nodes, 146 | nodeLocations: nodeLocations ?? old.nodeLocations, 147 | members: members ?? old.members, 148 | isMember: isMember, 149 | ); 150 | } 151 | 152 | factory OsmElement.fromJson(Map data) { 153 | return OsmElement( 154 | id: OsmId.fromString(data['osmid']), 155 | version: data['version'], 156 | timestamp: DateTime.fromMillisecondsSinceEpoch(data['timestamp']), 157 | tags: {}, 158 | ); 159 | } 160 | 161 | Map toJson() => {}; 162 | 163 | // void toXML(XmlBuilder builder, {String? changeset, bool visible = true}) { 164 | // } 165 | 166 | bool get isPoint => id.type == OsmElementType.node; 167 | bool get isGood => ElementKind.everything.matchesTags(tags); 168 | bool get isSnapTarget => 169 | id.type == OsmElementType.way; 170 | bool get isGeometryValid => 171 | nodes != null && 172 | nodes!.length >= 2 && 173 | nodes!.every((element) => nodeLocations?.containsKey(element) ?? false); 174 | 175 | bool get isArea => false; 176 | 177 | String get idVersion => '${id}v$version'; 178 | 179 | static String tagsToString(Map tags) => '{}'; 180 | } 181 | -------------------------------------------------------------------------------- /lib/models/note.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/draw_style.dart'; 2 | import 'package:every_door_plugin/helpers/geometry/geometry.dart'; 3 | import 'package:latlong2/latlong.dart' show LatLng; 4 | 5 | class BaseNote { 6 | static const kNoteGeohashPrecision = 6; 7 | 8 | int? id; 9 | final int? type; 10 | final LatLng location; 11 | final DateTime created; 12 | bool deleting; 13 | 14 | BaseNote( 15 | {required this.location, 16 | this.id, 17 | required this.type, 18 | DateTime? created, 19 | this.deleting = false}) 20 | : created = created ?? DateTime.now(); 21 | 22 | bool get isChanged => isNew || deleting; 23 | bool get isNew => (id ?? -1) < 0; 24 | 25 | /// Reverts changes if possible (except isNew) and returns true if successful. 26 | bool revert() { 27 | if (!isChanged || isNew) return false; 28 | if (deleting) deleting = false; 29 | if (isChanged) 30 | throw UnimplementedError('A note has a state that cannot be reverted.'); 31 | return true; 32 | } 33 | 34 | factory BaseNote.fromJson(Map data) { 35 | switch (data['type']) { 36 | case MapNote.dbType: 37 | return MapNote.fromJson(data); 38 | case OsmNote.dbType: 39 | return OsmNote.fromJson(data); 40 | case MapDrawing.dbType: 41 | return MapDrawing.fromJson(data); 42 | } 43 | throw ArgumentError('Unknown note type in the database: ${data["type"]}'); 44 | } 45 | 46 | Map toJson() => {}; 47 | } 48 | 49 | class MapNote extends BaseNote { 50 | static const kMaxLength = 40; 51 | static const dbType = 1; 52 | final String? author; 53 | String message; 54 | 55 | MapNote( 56 | {super.id, 57 | required super.location, 58 | this.author, 59 | required this.message, 60 | super.deleting, 61 | super.created}) 62 | : super(type: dbType); 63 | 64 | factory MapNote.fromJson(Map data) { 65 | return MapNote( 66 | id: data['id'], 67 | location: LatLng(0, 0), 68 | author: data['author'], 69 | message: data['message'], 70 | created: DateTime.fromMillisecondsSinceEpoch(data['created']), 71 | deleting: data['is_deleting'] == 1, 72 | ); 73 | } 74 | 75 | @override 76 | Map toJson() { 77 | return { 78 | ...super.toJson(), 79 | 'author': author, 80 | 'message': message, 81 | }; 82 | } 83 | 84 | @override 85 | String toString() => 'MapNote($id, $location, "$message" by $author)'; 86 | } 87 | 88 | class OsmNoteComment { 89 | final String? author; 90 | String message; 91 | final DateTime date; 92 | final bool isNew; 93 | 94 | OsmNoteComment({ 95 | this.author, 96 | required this.message, 97 | DateTime? date, 98 | this.isNew = false, 99 | }) : date = date ?? DateTime.now(); 100 | 101 | factory OsmNoteComment.fromJson(Map data) { 102 | return OsmNoteComment( 103 | author: data['author'], 104 | message: data['message'], 105 | date: DateTime.fromMillisecondsSinceEpoch(data['date']), 106 | isNew: data['isNew'], 107 | ); 108 | } 109 | 110 | Map toJson() { 111 | return { 112 | if (author != null) 'author': author, 113 | 'message': message, 114 | 'date': date.millisecondsSinceEpoch, 115 | 'isNew': isNew, 116 | }; 117 | } 118 | 119 | @override 120 | String toString() => 'Comment(${isNew ? "new " : ""}"$message" by $author)'; 121 | } 122 | 123 | class OsmNote extends BaseNote { 124 | static const dbType = 2; 125 | final List comments; 126 | 127 | OsmNote({ 128 | super.id, 129 | required super.location, 130 | this.comments = const [], 131 | super.created, 132 | super.deleting, 133 | }) : super(type: dbType); 134 | 135 | String? get author => comments.isEmpty ? null : comments.first.author; 136 | String? get message => comments.isEmpty ? null : comments.first.message; 137 | bool get hasNewComments => comments.any((c) => c.isNew); 138 | 139 | @override 140 | bool get isChanged => super.isChanged || hasNewComments; 141 | 142 | @override 143 | bool revert() { 144 | comments.removeWhere((c) => c.isNew); 145 | return super.revert(); 146 | } 147 | 148 | String? getNoteTitle() { 149 | return (message?.length ?? 0) < 100 ? message : message?.substring(0, 100); 150 | } 151 | 152 | factory OsmNote.fromJson(Map data) { 153 | return OsmNote( 154 | id: data['id'], 155 | location: LatLng(0, 0), 156 | created: DateTime.fromMillisecondsSinceEpoch(data['created']), 157 | deleting: data['is_deleting'] == 1, 158 | comments: [], 159 | ); 160 | } 161 | 162 | @override 163 | Map toJson() => {}; 164 | 165 | @override 166 | String toString() => 167 | 'OsmNote(${deleting ? "closing " : (isChanged ? "changed " : "")}$id, $location, $comments)'; 168 | } 169 | 170 | class MapDrawing extends BaseNote { 171 | static const dbType = 3; 172 | final LineString path; 173 | final String? author; 174 | final String pathType; 175 | 176 | MapDrawing({ 177 | super.id, 178 | required this.path, 179 | required this.pathType, 180 | this.author, 181 | super.created, 182 | super.deleting, 183 | }) : super(type: dbType, location: path.nodes[path.nodes.length >> 1]); 184 | 185 | DrawingStyle get style => kTypeStyles[pathType] ?? kUnknownStyle; 186 | 187 | factory MapDrawing.fromJson(Map data) { 188 | final coords = []; 189 | for (final part in (data['coords'] as String).split('|')) { 190 | final latlon = 191 | part.split(';').map((s) => double.parse(s.trim())).toList(); 192 | if (latlon.length == 2) coords.add(LatLng(latlon[0], latlon[1])); 193 | } 194 | return MapDrawing( 195 | id: data['id'], 196 | pathType: data['path_type'], 197 | author: data['author'], 198 | path: LineString(coords), 199 | created: DateTime.fromMillisecondsSinceEpoch(data['created']), 200 | deleting: data['is_deleting'] == 1, 201 | ); 202 | } 203 | 204 | @override 205 | Map toJson() => {}; 206 | 207 | @override 208 | String toString() => 'MapDrawing($id, "$pathType", $location)'; 209 | } 210 | -------------------------------------------------------------------------------- /lib/plugins/bindings/plugins/every_door_plugin.eval.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers 2 | import 'package:dart_eval/dart_eval_bridge.dart'; 3 | import 'package:dart_eval/stdlib/core.dart'; 4 | import 'package:every_door_plugin/plugins/every_door_plugin.dart'; 5 | import 'package:every_door_plugin/plugins/interface.dart'; 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter_eval/widgets.dart'; 8 | import 'package:every_door_plugin/plugins/bindings/plugins/interface.eval.dart'; 9 | 10 | /// dart_eval bridge binding for [EveryDoorPlugin] 11 | class $EveryDoorPlugin$bridge extends EveryDoorPlugin 12 | with $Bridge { 13 | /// Forwarded constructor for [EveryDoorPlugin.new] 14 | $EveryDoorPlugin$bridge(); 15 | 16 | /// Configure this class for use in a [Runtime] 17 | static void configureForRuntime(Runtime runtime) { 18 | runtime.registerBridgeFunc( 19 | 'package:every_door/plugins/every_door_plugin.dart', 20 | 'EveryDoorPlugin.', 21 | $EveryDoorPlugin$bridge.$new, 22 | isBridge: true, 23 | ); 24 | } 25 | 26 | /// Compile-time type specification of [$EveryDoorPlugin$bridge] 27 | static const $spec = BridgeTypeSpec( 28 | 'package:every_door/plugins/every_door_plugin.dart', 29 | 'EveryDoorPlugin', 30 | ); 31 | 32 | /// Compile-time type declaration of [$EveryDoorPlugin$bridge] 33 | static const $type = BridgeTypeRef($spec); 34 | 35 | /// Compile-time class declaration of [$EveryDoorPlugin] 36 | static const $declaration = BridgeClassDef( 37 | BridgeClassType($type), 38 | constructors: { 39 | '': BridgeConstructorDef( 40 | BridgeFunctionDef( 41 | returns: BridgeTypeAnnotation($type), 42 | namedParams: [], 43 | params: [], 44 | ), 45 | isFactory: false, 46 | ), 47 | }, 48 | 49 | methods: { 50 | 'install': BridgeMethodDef( 51 | BridgeFunctionDef( 52 | returns: BridgeTypeAnnotation( 53 | BridgeTypeRef(CoreTypes.future, [ 54 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 55 | ]), 56 | ), 57 | namedParams: [], 58 | params: [ 59 | BridgeParameter( 60 | 'app', 61 | BridgeTypeAnnotation( 62 | BridgeTypeRef( 63 | BridgeTypeSpec( 64 | 'package:every_door/plugins/interface.dart', 65 | 'EveryDoorApp', 66 | ), 67 | [], 68 | ), 69 | ), 70 | false, 71 | ), 72 | ], 73 | ), 74 | ), 75 | 76 | 'uninstall': BridgeMethodDef( 77 | BridgeFunctionDef( 78 | returns: BridgeTypeAnnotation( 79 | BridgeTypeRef(CoreTypes.future, [ 80 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 81 | ]), 82 | ), 83 | namedParams: [], 84 | params: [ 85 | BridgeParameter( 86 | 'app', 87 | BridgeTypeAnnotation( 88 | BridgeTypeRef( 89 | BridgeTypeSpec( 90 | 'package:every_door/plugins/interface.dart', 91 | 'EveryDoorApp', 92 | ), 93 | [], 94 | ), 95 | ), 96 | false, 97 | ), 98 | ], 99 | ), 100 | ), 101 | 102 | 'buildSettingsPane': BridgeMethodDef( 103 | BridgeFunctionDef( 104 | returns: BridgeTypeAnnotation( 105 | BridgeTypeRef( 106 | BridgeTypeSpec( 107 | 'package:flutter/src/widgets/framework.dart', 108 | 'Widget', 109 | ), 110 | [], 111 | ), 112 | nullable: true, 113 | ), 114 | namedParams: [], 115 | params: [ 116 | BridgeParameter( 117 | 'app', 118 | BridgeTypeAnnotation( 119 | BridgeTypeRef( 120 | BridgeTypeSpec( 121 | 'package:every_door/plugins/interface.dart', 122 | 'EveryDoorApp', 123 | ), 124 | [], 125 | ), 126 | ), 127 | false, 128 | ), 129 | 130 | BridgeParameter( 131 | 'context', 132 | BridgeTypeAnnotation( 133 | BridgeTypeRef( 134 | BridgeTypeSpec( 135 | 'package:flutter/src/widgets/framework.dart', 136 | 'BuildContext', 137 | ), 138 | [], 139 | ), 140 | ), 141 | false, 142 | ), 143 | ], 144 | ), 145 | ), 146 | }, 147 | getters: {}, 148 | setters: {}, 149 | fields: {}, 150 | wrap: false, 151 | bridge: true, 152 | ); 153 | 154 | /// Proxy for the [EveryDoorPlugin.new] constructor 155 | static $Value? $new(Runtime runtime, $Value? thisValue, List<$Value?> args) { 156 | return $EveryDoorPlugin$bridge(); 157 | } 158 | 159 | @override 160 | $Value? $bridgeGet(String identifier) { 161 | switch (identifier) { 162 | case 'install': 163 | return $Function((runtime, target, args) { 164 | final result = super.install(args[1]!.$value); 165 | return $Future.wrap(result.then((e) => null)); 166 | }); 167 | case 'uninstall': 168 | return $Function((runtime, target, args) { 169 | final result = super.uninstall(args[1]!.$value); 170 | return $Future.wrap(result.then((e) => null)); 171 | }); 172 | case 'buildSettingsPane': 173 | return $Function((runtime, target, args) { 174 | final result = super.buildSettingsPane( 175 | args[1]!.$value, 176 | args[2]!.$value, 177 | ); 178 | return result == null ? const $null() : $Widget.wrap(result); 179 | }); 180 | } 181 | return null; 182 | } 183 | 184 | @override 185 | void $bridgeSet(String identifier, $Value value) {} 186 | 187 | @override 188 | Future install(EveryDoorApp app) => 189 | $_invoke('install', [$EveryDoorApp.wrap(app)]); 190 | 191 | @override 192 | Future uninstall(EveryDoorApp app) => 193 | $_invoke('uninstall', [$EveryDoorApp.wrap(app)]); 194 | 195 | @override 196 | Widget? buildSettingsPane(EveryDoorApp app, BuildContext context) => $_invoke( 197 | 'buildSettingsPane', 198 | [$EveryDoorApp.wrap(app), $BuildContext.wrap(context)], 199 | ); 200 | } 201 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json, utf8; 2 | 3 | import 'package:every_door_plugin/helpers/auth/provider.dart'; 4 | import 'package:every_door_plugin/helpers/multi_icon.dart'; 5 | import 'package:every_door_plugin/plugins/every_door_plugin.dart'; 6 | import 'package:every_door_plugin/plugins/ext_overlay.dart'; 7 | import 'package:every_door_plugin/plugins/interface.dart'; 8 | import 'package:every_door_plugin/screens/modes/definitions/classic.dart'; 9 | import 'package:every_door_plugin/widgets/map_button.dart'; 10 | import 'package:every_door_plugin/models/amenity.dart'; 11 | import 'package:flutter/material.dart'; 12 | import 'package:flutter_map/flutter_map.dart'; 13 | import 'package:http/http.dart' as http; 14 | import 'package:latlong2/latlong.dart' show LatLng; 15 | import 'package:logging/logging.dart'; 16 | 17 | EveryDoorPlugin main() => PanoramaxDemoPlugin(); 18 | 19 | class PanoramaxDemoPlugin extends EveryDoorPlugin { 20 | static const kEndpoint = 'panoramax.openstreetmap.fr'; 21 | bool apiFound = false; 22 | 23 | @override 24 | Future install(EveryDoorApp app) async { 25 | app.logger.info("Installing plugin!"); 26 | final apiResponse = await http.get( 27 | Uri.https(kEndpoint, '/api/configuration'), 28 | ); 29 | if (apiResponse.statusCode == 200) { 30 | final response = json.decode(utf8.decode(apiResponse.bodyBytes)); 31 | app.logger.info('API response ok, name: ${response["name"]["label"]}'); 32 | apiFound = true; 33 | } 34 | 35 | // app.addMode(TestMode(app)); 36 | 37 | app.events.onDownload((location) async { 38 | // TODO: download and put into the database. 39 | // final bounds = boundsFromRadius(location, 1000); 40 | }); 41 | 42 | app.events.onModeCreated((mode) async { 43 | app.logger.info("Mode created: ${mode.name}"); 44 | 45 | if (mode.name == 'micro') { 46 | mode.addMapButton( 47 | MapButton( 48 | icon: MultiIcon(emoji: 'P'), 49 | onPressed: (context) { 50 | app.providers.location = LatLng(59.409680, 24.631112); 51 | }, 52 | ), 53 | ); 54 | } 55 | }); 56 | 57 | if (apiFound) { 58 | app.addOverlay( 59 | ExtOverlay( 60 | id: 'panoramax', 61 | build: (context, data) { 62 | if (data == null || data is! List) return Container(); 63 | final photos = data as List; 64 | if (photos.isEmpty) return Container(); 65 | return MarkerLayer( 66 | markers: [ 67 | for (final photo in photos) buildMarker(app, context, photo), 68 | ], 69 | ); 70 | }, 71 | update: (bounds) async { 72 | return await queryPhotos(app.logger, bounds); 73 | }, 74 | ), 75 | ); 76 | } 77 | } 78 | 79 | Marker buildMarker( 80 | EveryDoorApp app, 81 | BuildContext context, 82 | PanoramaxPhoto photo, 83 | ) => Marker( 84 | point: photo.location, 85 | rotate: true, 86 | child: GestureDetector( 87 | behavior: HitTestBehavior.opaque, 88 | onTap: () async { 89 | final url = photo.thumbnailUrl; // photo.imageUrl ?? photo.thumbnailUrl; 90 | app.logger.info('tapped on a photo ${photo.id} with url $url'); 91 | if (url == null) { 92 | ScaffoldMessenger.of(context).showSnackBar( 93 | SnackBar(content: Text('Photo ${photo.id} has no image url')), 94 | ); 95 | } else { 96 | await showModalBottomSheet( 97 | context: context, 98 | builder: (_) => SafeArea(child: Image.network(url)), 99 | ); 100 | } 101 | }, 102 | child: Text('📷', style: TextStyle(fontSize: 30.0)), 103 | ), 104 | height: 30, 105 | width: 30, 106 | ); 107 | 108 | Future> queryPhotos( 109 | Logger log, 110 | LatLngBounds bounds, 111 | ) async { 112 | final response = await http.get( 113 | Uri.https(kEndpoint, '/api/search', { 114 | 'bbox': [ 115 | bounds.west, 116 | bounds.south, 117 | bounds.east, 118 | bounds.north, 119 | ].join(','), 120 | 'limit': '40', 121 | }), 122 | ); 123 | if (response.statusCode != 200) { 124 | log.warning('Got response ${response.statusCode} ${response.body}'); 125 | return []; 126 | } 127 | final data = json.decode(utf8.decode(response.bodyBytes)) as Map; 128 | if (!data.containsKey('features')) return []; 129 | final result = []; 130 | for (final feature in data['features'] as List) { 131 | if (feature is Map) { 132 | try { 133 | result.add(PanoramaxPhoto.fromJson(feature)); 134 | } on Exception catch (_) { 135 | log.warning('Failed to decode json: $feature'); 136 | } 137 | } 138 | } 139 | log.info('Downloaded ${result.length} photos'); 140 | return result; 141 | } 142 | 143 | @override 144 | Widget buildSettingsPane(EveryDoorApp app, BuildContext context) { 145 | return Column( 146 | children: [ 147 | SwitchListTile( 148 | title: Text('Better icon'), 149 | value: app.preferences.getBool('better_icon') ?? false, 150 | onChanged: (bool value) async { 151 | await app.preferences.setBool('better_icon', value); 152 | app.repaint(); 153 | }, 154 | ), 155 | ], 156 | ); 157 | } 158 | } 159 | 160 | class PanoramaxPhoto { 161 | final String id; 162 | final String? thumbnailUrl; 163 | final String? imageUrl; 164 | final bool ready; 165 | final LatLng location; 166 | 167 | PanoramaxPhoto({ 168 | required this.id, 169 | this.thumbnailUrl, 170 | this.imageUrl, 171 | required this.location, 172 | required this.ready, 173 | }); 174 | 175 | factory PanoramaxPhoto.fromJson(Map data) { 176 | final props = data['properties'] as Map; 177 | final thumbnail = props['geovisio:thumbnail']; 178 | final image = props['geovisio:image']; 179 | final coords = data['geometry']['coordinates'] as List; 180 | return PanoramaxPhoto( 181 | id: data['id'], 182 | ready: props['geovisio:status'] == 'ready', 183 | thumbnailUrl: thumbnail is String ? thumbnail : null, 184 | imageUrl: image is String ? image : null, 185 | location: LatLng(coords[1], coords[0]), 186 | ); 187 | } 188 | } 189 | 190 | class TestMode extends ClassicModeDefinition { 191 | TestMode(EveryDoorApp app) : super.fromPlugin(app); 192 | 193 | @override 194 | MultiIcon getIcon(BuildContext context, bool outlined) => 195 | MultiIcon(emoji: '⭐'); 196 | 197 | @override 198 | String get name => 'test'; 199 | 200 | @override 201 | bool isOurKind(OsmChange element) => true; 202 | } 203 | -------------------------------------------------------------------------------- /lib/plugins/bindings/helpers/plugin_i18n.eval.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers 2 | import 'package:dart_eval/dart_eval_bridge.dart'; 3 | import 'package:every_door_plugin/helpers/plugin_i18n.dart'; 4 | import 'package:dart_eval/stdlib/core.dart'; 5 | 6 | /// dart_eval wrapper binding for [PluginLocalizationsBranch] 7 | class $PluginLocalizationsBranch implements $Instance { 8 | /// Configure this class for use in a [Runtime] 9 | static void configureForRuntime(Runtime runtime) { 10 | } 11 | 12 | /// Compile-time type specification of [$PluginLocalizationsBranch] 13 | static const $spec = BridgeTypeSpec( 14 | 'package:every_door/helpers/plugin_i18n.dart', 15 | 'PluginLocalizationsBranch', 16 | ); 17 | 18 | /// Compile-time type declaration of [$PluginLocalizationsBranch] 19 | static const $type = BridgeTypeRef($spec); 20 | 21 | /// Compile-time class declaration of [$PluginLocalizationsBranch] 22 | static const $declaration = BridgeClassDef( 23 | BridgeClassType($type), 24 | constructors: { 25 | }, 26 | 27 | methods: { 28 | 'translateCtx': BridgeMethodDef( 29 | BridgeFunctionDef( 30 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 31 | namedParams: [ 32 | BridgeParameter( 33 | 'args', 34 | BridgeTypeAnnotation( 35 | BridgeTypeRef(CoreTypes.map, [ 36 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 37 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.dynamic)), 38 | ]), 39 | nullable: true, 40 | ), 41 | true, 42 | ), 43 | ], 44 | params: [ 45 | BridgeParameter( 46 | 'context', 47 | BridgeTypeAnnotation( 48 | BridgeTypeRef( 49 | BridgeTypeSpec( 50 | 'package:flutter/src/widgets/framework.dart', 51 | 'BuildContext', 52 | ), 53 | [], 54 | ), 55 | ), 56 | false, 57 | ), 58 | 59 | BridgeParameter( 60 | 'key', 61 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 62 | false, 63 | ), 64 | ], 65 | ), 66 | ), 67 | 68 | 'translate': BridgeMethodDef( 69 | BridgeFunctionDef( 70 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 71 | namedParams: [ 72 | BridgeParameter( 73 | 'args', 74 | BridgeTypeAnnotation( 75 | BridgeTypeRef(CoreTypes.map, [ 76 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 77 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.dynamic)), 78 | ]), 79 | nullable: true, 80 | ), 81 | true, 82 | ), 83 | ], 84 | params: [ 85 | BridgeParameter( 86 | 'locale', 87 | BridgeTypeAnnotation( 88 | BridgeTypeRef(BridgeTypeSpec('dart:ui', 'Locale'), []), 89 | ), 90 | false, 91 | ), 92 | 93 | BridgeParameter( 94 | 'key', 95 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 96 | false, 97 | ), 98 | ], 99 | ), 100 | ), 101 | 102 | 'translateList': BridgeMethodDef( 103 | BridgeFunctionDef( 104 | returns: BridgeTypeAnnotation( 105 | BridgeTypeRef(CoreTypes.list, [ 106 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 107 | ]), 108 | ), 109 | namedParams: [], 110 | params: [ 111 | BridgeParameter( 112 | 'locale', 113 | BridgeTypeAnnotation( 114 | BridgeTypeRef(BridgeTypeSpec('dart:ui', 'Locale'), []), 115 | ), 116 | false, 117 | ), 118 | 119 | BridgeParameter( 120 | 'key', 121 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 122 | false, 123 | ), 124 | ], 125 | ), 126 | ), 127 | }, 128 | getters: {}, 129 | setters: {}, 130 | fields: {}, 131 | wrap: true, 132 | bridge: false, 133 | ); 134 | 135 | final $Instance _superclass; 136 | 137 | @override 138 | final PluginLocalizationsBranch $value; 139 | 140 | @override 141 | PluginLocalizationsBranch get $reified => $value; 142 | 143 | /// Wrap a [PluginLocalizationsBranch] in a [$PluginLocalizationsBranch] 144 | $PluginLocalizationsBranch.wrap(this.$value) : _superclass = $Object($value); 145 | 146 | @override 147 | int $getRuntimeType(Runtime runtime) => runtime.lookupType($spec); 148 | 149 | @override 150 | $Value? $getProperty(Runtime runtime, String identifier) { 151 | switch (identifier) { 152 | case 'translateCtx': 153 | return __translateCtx; 154 | 155 | case 'translate': 156 | return __translate; 157 | 158 | case 'translateList': 159 | return __translateList; 160 | } 161 | return _superclass.$getProperty(runtime, identifier); 162 | } 163 | 164 | static const $Function __translateCtx = $Function(_translateCtx); 165 | static $Value? _translateCtx( 166 | Runtime runtime, 167 | $Value? target, 168 | List<$Value?> args, 169 | ) { 170 | final self = target! as $PluginLocalizationsBranch; 171 | final result = self.$value.translateCtx( 172 | args[0]!.$value, 173 | args[1]!.$value, 174 | args: (args[2]?.$reified as Map?)?.cast(), 175 | ); 176 | return $String(result); 177 | } 178 | 179 | static const $Function __translate = $Function(_translate); 180 | static $Value? _translate( 181 | Runtime runtime, 182 | $Value? target, 183 | List<$Value?> args, 184 | ) { 185 | final self = target! as $PluginLocalizationsBranch; 186 | final result = self.$value.translate( 187 | args[0]!.$value, 188 | args[1]!.$value, 189 | args: (args[2]?.$reified as Map?)?.cast(), 190 | ); 191 | return $String(result); 192 | } 193 | 194 | static const $Function __translateList = $Function(_translateList); 195 | static $Value? _translateList( 196 | Runtime runtime, 197 | $Value? target, 198 | List<$Value?> args, 199 | ) { 200 | final self = target! as $PluginLocalizationsBranch; 201 | final result = self.$value.translateList(args[0]!.$value, args[1]!.$value); 202 | return $List.view(result, (e) => $String(e)); 203 | } 204 | 205 | @override 206 | void $setProperty(Runtime runtime, String identifier, $Value value) { 207 | return _superclass.$setProperty(runtime, identifier, value); 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /lib/plugins/bindings/plugins/events.eval.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers 2 | import 'package:dart_eval/dart_eval_bridge.dart'; 3 | import 'package:every_door_plugin/plugins/events.dart'; 4 | import 'package:every_door_plugin/screens/modes/definitions/base.dart'; 5 | import 'package:latlong2/latlong.dart'; 6 | import 'package:dart_eval/stdlib/core.dart'; 7 | import 'package:every_door_plugin/plugins/bindings/screens/modes/definitions/base.eval.dart'; 8 | import 'package:flutter_map_eval/latlong2/latlong2_eval.dart'; 9 | 10 | /// dart_eval wrapper binding for [PluginEvents] 11 | class $PluginEvents implements $Instance { 12 | /// Configure this class for use in a [Runtime] 13 | static void configureForRuntime(Runtime runtime) { 14 | } 15 | 16 | /// Compile-time type specification of [$PluginEvents] 17 | static const $spec = BridgeTypeSpec( 18 | 'package:every_door/plugins/events.dart', 19 | 'PluginEvents', 20 | ); 21 | 22 | /// Compile-time type declaration of [$PluginEvents] 23 | static const $type = BridgeTypeRef($spec); 24 | 25 | /// Compile-time class declaration of [$PluginEvents] 26 | static const $declaration = BridgeClassDef( 27 | BridgeClassType($type), 28 | constructors: { 29 | }, 30 | 31 | methods: { 32 | 'onModeCreated': BridgeMethodDef( 33 | BridgeFunctionDef( 34 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 35 | namedParams: [], 36 | params: [ 37 | BridgeParameter( 38 | 'callback', 39 | BridgeTypeAnnotation( 40 | BridgeTypeRef.genericFunction( 41 | BridgeFunctionDef( 42 | returns: BridgeTypeAnnotation( 43 | BridgeTypeRef(CoreTypes.dynamic), 44 | ), 45 | params: [ 46 | BridgeParameter( 47 | 'mode', 48 | BridgeTypeAnnotation( 49 | BridgeTypeRef( 50 | BridgeTypeSpec( 51 | 'package:every_door/screens/modes/definitions/base.dart', 52 | 'BaseModeDefinition', 53 | ), 54 | [], 55 | ), 56 | ), 57 | false, 58 | ), 59 | ], 60 | namedParams: [], 61 | ), 62 | ), 63 | ), 64 | false, 65 | ), 66 | ], 67 | ), 68 | ), 69 | 70 | 'onUpload': BridgeMethodDef( 71 | BridgeFunctionDef( 72 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 73 | namedParams: [], 74 | params: [ 75 | BridgeParameter( 76 | 'callback', 77 | BridgeTypeAnnotation( 78 | BridgeTypeRef.genericFunction( 79 | BridgeFunctionDef( 80 | returns: BridgeTypeAnnotation( 81 | BridgeTypeRef(CoreTypes.dynamic), 82 | ), 83 | params: [], 84 | namedParams: [], 85 | ), 86 | ), 87 | ), 88 | false, 89 | ), 90 | ], 91 | ), 92 | ), 93 | 94 | 'onDownload': BridgeMethodDef( 95 | BridgeFunctionDef( 96 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 97 | namedParams: [], 98 | params: [ 99 | BridgeParameter( 100 | 'callback', 101 | BridgeTypeAnnotation( 102 | BridgeTypeRef.genericFunction( 103 | BridgeFunctionDef( 104 | returns: BridgeTypeAnnotation( 105 | BridgeTypeRef(CoreTypes.dynamic), 106 | ), 107 | params: [ 108 | BridgeParameter( 109 | '', 110 | BridgeTypeAnnotation( 111 | BridgeTypeRef( 112 | BridgeTypeSpec( 113 | 'package:latlong2/latlong.dart', 114 | 'LatLng', 115 | ), 116 | [], 117 | ), 118 | ), 119 | false, 120 | ), 121 | ], 122 | namedParams: [], 123 | ), 124 | ), 125 | ), 126 | false, 127 | ), 128 | ], 129 | ), 130 | ), 131 | }, 132 | getters: {}, 133 | setters: {}, 134 | fields: {}, 135 | wrap: true, 136 | bridge: false, 137 | ); 138 | 139 | final $Instance _superclass; 140 | 141 | @override 142 | final PluginEvents $value; 143 | 144 | @override 145 | PluginEvents get $reified => $value; 146 | 147 | /// Wrap a [PluginEvents] in a [$PluginEvents] 148 | $PluginEvents.wrap(this.$value) : _superclass = $Object($value); 149 | 150 | @override 151 | int $getRuntimeType(Runtime runtime) => runtime.lookupType($spec); 152 | 153 | @override 154 | $Value? $getProperty(Runtime runtime, String identifier) { 155 | switch (identifier) { 156 | case 'onModeCreated': 157 | return __onModeCreated; 158 | 159 | case 'onUpload': 160 | return __onUpload; 161 | 162 | case 'onDownload': 163 | return __onDownload; 164 | } 165 | return _superclass.$getProperty(runtime, identifier); 166 | } 167 | 168 | static const $Function __onModeCreated = $Function(_onModeCreated); 169 | static $Value? _onModeCreated( 170 | Runtime runtime, 171 | $Value? target, 172 | List<$Value?> args, 173 | ) { 174 | final self = target! as $PluginEvents; 175 | self.$value.onModeCreated((BaseModeDefinition mode) { 176 | return (args[0]! as EvalCallable)(runtime, null, [ 177 | $BaseModeDefinition.wrap(mode), 178 | ])?.$value; 179 | }); 180 | return null; 181 | } 182 | 183 | static const $Function __onUpload = $Function(_onUpload); 184 | static $Value? _onUpload( 185 | Runtime runtime, 186 | $Value? target, 187 | List<$Value?> args, 188 | ) { 189 | final self = target! as $PluginEvents; 190 | self.$value.onUpload(() { 191 | return (args[0]! as EvalCallable)(runtime, null, [])?.$value; 192 | }); 193 | return null; 194 | } 195 | 196 | static const $Function __onDownload = $Function(_onDownload); 197 | static $Value? _onDownload( 198 | Runtime runtime, 199 | $Value? target, 200 | List<$Value?> args, 201 | ) { 202 | final self = target! as $PluginEvents; 203 | self.$value.onDownload((LatLng arg0) { 204 | return (args[0]! as EvalCallable)(runtime, null, [ 205 | $LatLng.wrap(arg0), 206 | ])?.$value; 207 | }); 208 | return null; 209 | } 210 | 211 | @override 212 | void $setProperty(Runtime runtime, String identifier, $Value value) { 213 | return _superclass.$setProperty(runtime, identifier, value); 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /lib/helpers/tags/tag_matcher.dart: -------------------------------------------------------------------------------- 1 | import 'package:every_door_plugin/helpers/tags/main_key.dart'; 2 | import 'package:every_door_plugin/models/amenity.dart'; 3 | 4 | /// A class for matching tag lists against a set of rules. 5 | /// Contains rules for individual keys (see [ValueMatcher]), 6 | /// and lists of [good] and [missing] keys to validate. 7 | class TagMatcher { 8 | /// Empty matcher that matches everything. 9 | static const empty = TagMatcher({}); 10 | 11 | /// Rules for matching values for a key. 12 | final Map rules; 13 | 14 | /// List of keys to be accepted without looking at the rules. 15 | /// Works only for the "onlyKey" parameter of [matches] and [matchesChange]. 16 | final Set good; 17 | 18 | /// List of keys that should be missing. If it's not empty and 19 | /// _any_ of the keys here are missing, and all the rules match 20 | /// or are skipped, then [matches] returns "true". 21 | /// Unlike for [good], we don't strip prefixes here for matching. 22 | /// This is used for matching objects that lack some additional tags. 23 | final Set missing; 24 | 25 | const TagMatcher(this.rules, {this.good = const {}, this.missing = const {}}); 26 | 27 | /// Returns "true" only if nothing has been initialized. 28 | bool get isEmpty => rules.isEmpty && good.isEmpty && missing.isEmpty; 29 | 30 | /// Tests a set of tags for a match. Pass [onlyKey] to test only 31 | /// rules for this single key, and also use [good] key set. 32 | /// A prefix in [onlyKey] is stripped, but not in other keys. 33 | /// 34 | /// For matching an [OsmChange] object, see [matchesChange]. 35 | bool matches(Map tags, [String? onlyKey]) { 36 | assert(onlyKey == null || tags.containsKey(onlyKey)); 37 | 38 | final rawKey = clearPrefixNull(onlyKey); 39 | if (good.contains(rawKey)) return true; 40 | if (missing.any((k) => !tags.containsKey(k))) return true; 41 | if (rules.isEmpty) return missing.isEmpty && good.isEmpty; 42 | 43 | if (onlyKey != null) { 44 | final rule = rules[rawKey]; 45 | if (rule != null && rule.matches(tags[onlyKey]!, tags)) return true; 46 | } else { 47 | for (final kr in rules.entries) { 48 | final value = tags[kr.key]; 49 | if (value != null && kr.value.matches(value, tags)) return true; 50 | } 51 | } 52 | 53 | return false; 54 | } 55 | 56 | /// Tests an [OsmChange] object for a match. Performs exactly 57 | /// as [match], but doesn't call [OsmChange.getFullTags]. 58 | bool matchesChange(OsmChange change, [String? onlyKey]) { 59 | assert(onlyKey == null || change[onlyKey] != null); 60 | 61 | final rawKey = clearPrefixNull(onlyKey); 62 | if (good.contains(rawKey)) return true; 63 | if (missing.any((k) => change[k] == null)) return true; 64 | if (rules.isEmpty) return missing.isEmpty && good.isEmpty; 65 | 66 | if (onlyKey != null) { 67 | final rule = rules[rawKey]; 68 | if (rule != null && rule.matchesChange(change[onlyKey]!, change)) 69 | return true; 70 | } else { 71 | for (final kr in rules.entries) { 72 | final value = change[kr.key]; 73 | if (value != null && kr.value.matchesChange(value, change)) return true; 74 | } 75 | } 76 | 77 | return false; 78 | } 79 | 80 | /// Merges this tag matcher with another. Used internally. 81 | /// Rules are merged using [ValueMatcher.mergeWith], [good] keys 82 | /// are united, [missing] set is replaced. 83 | TagMatcher mergeWith(TagMatcher? another) { 84 | if (another == null) return this; 85 | 86 | final newRules = Map.of(rules); 87 | for (final kv in another.rules.entries) { 88 | newRules[kv.key] = newRules[kv.key]?.mergeWith(kv.value) ?? kv.value; 89 | } 90 | 91 | return TagMatcher( 92 | newRules, 93 | good: good.union(another.good), 94 | missing: another.missing, 95 | ); 96 | } 97 | 98 | /// Builds a class instance from a structure. It expects a plain map 99 | /// with tag keys for keys, and [ValueMatcher] structures for values. 100 | /// Two keys are exceptions and should contain lists of strings: 101 | /// "$good" (see [good]) and "$missing" (see [missing]). 102 | factory TagMatcher.fromJson(Map? data) { 103 | if (data == null) return empty; 104 | 105 | final rules = data.map((k, v) => MapEntry(k, ValueMatcher.fromJson(v))); 106 | rules.removeWhere((k, v) => k.startsWith('\$')); 107 | 108 | return TagMatcher( 109 | rules, 110 | good: Set.of(data['\$good'] ?? const []), 111 | missing: Set.of(data['\$missing'] ?? const []), 112 | ); 113 | } 114 | } 115 | 116 | /// This class matches tag values to a set of rules. 117 | class ValueMatcher { 118 | /// Those values are forbidden, the matcher will return "false". 119 | final Set except; 120 | 121 | /// If not empty, this list should include every allowed value. 122 | /// Keys from [when] are also considered, so they can be omitted. 123 | final Set only; 124 | 125 | /// Conditional rules for some values. They allow to check other 126 | /// sub-tags, e.g. "recycling_type=*" for "amenity=recycling". 127 | /// When [only] and [except] are empty, only values in this map 128 | /// are accepted (it works as "only"). 129 | final Map when; 130 | 131 | /// When updating a matcher, replace all fields or add values. 132 | final bool replace; 133 | 134 | const ValueMatcher({ 135 | this.except = const {}, 136 | this.only = const {}, 137 | this.when = const {}, 138 | this.replace = true, 139 | }); 140 | 141 | /// Tests the value to match all the rules. 142 | bool matches(String value, Map tags) { 143 | if (only.isNotEmpty && !(only.contains(value) || when.containsKey(value))) 144 | return false; 145 | if (except.isNotEmpty && except.contains(value)) return false; 146 | if (!(when[value]?.matches(tags) ?? true)) return false; 147 | if (when.isNotEmpty && 148 | except.isEmpty && 149 | only.isEmpty && 150 | !when.containsKey(value)) return false; 151 | return true; 152 | } 153 | 154 | /// Tests an [OsmChange] object for a match. Performs exactly 155 | /// as [match], but doesn't call [OsmChange.getFullTags]. 156 | bool matchesChange(String value, OsmChange change) { 157 | if (only.isNotEmpty && !(only.contains(value) || when.containsKey(value))) 158 | return false; 159 | if (except.isNotEmpty && except.contains(value)) return false; 160 | if (!(when[value]?.matchesChange(change) ?? true)) return false; 161 | if (when.isNotEmpty && 162 | except.isEmpty && 163 | only.isEmpty && 164 | !when.containsKey(value)) return false; 165 | return true; 166 | } 167 | 168 | /// Merge two value matchers. Used internally when updating from 169 | /// an external source. 170 | ValueMatcher mergeWith(ValueMatcher another) { 171 | if (another.replace) return another; 172 | 173 | final newWhen = Map.of(when); 174 | newWhen.addAll(another.when); 175 | 176 | return ValueMatcher( 177 | except: except.union(another.except), 178 | only: only.union(another.only), 179 | when: newWhen, 180 | ); 181 | } 182 | 183 | /// Builds a class instance out of a structure. The structure 184 | /// is straightforward: a map with "except", "only", and "when" 185 | /// keys that replicated this class fields. 186 | factory ValueMatcher.fromJson(Map data) { 187 | return ValueMatcher( 188 | except: Set.of( 189 | (data['except'] as Iterable?)?.whereType() ?? 190 | const []), 191 | only: Set.of((data['only'] as Iterable?)?.whereType() ?? 192 | const []), 193 | when: (data['when'] as Map?) 194 | ?.map((k, v) => MapEntry(k, TagMatcher.fromJson(data['when']))) ?? 195 | const {}, 196 | replace: data['replace'] ?? true, 197 | ); 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /lib/plugins/bindings/every_door_eval.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_eval/dart_eval_bridge.dart'; 2 | import 'helpers/tags/element_kind.eval.dart'; 3 | import 'helpers/tags/tag_matcher.eval.dart'; 4 | import 'helpers/geometry/geometry.eval.dart'; 5 | import 'helpers/plugin_i18n.eval.dart'; 6 | import 'helpers/legend.eval.dart'; 7 | import 'helpers/multi_icon.eval.dart'; 8 | import 'helpers/auth/provider.eval.dart'; 9 | import 'helpers/auth/oauth2.eval.dart'; 10 | import 'helpers/auth/controller.eval.dart'; 11 | import 'models/imagery.eval.dart'; 12 | import 'models/note.eval.dart'; 13 | import 'models/osm_element.eval.dart'; 14 | import 'models/amenity.eval.dart'; 15 | import 'models/plugin.eval.dart'; 16 | import 'models/version.eval.dart'; 17 | import 'screens/modes/definitions/entrances.eval.dart'; 18 | import 'screens/modes/definitions/base.eval.dart'; 19 | import 'screens/modes/definitions/micro.eval.dart'; 20 | import 'screens/modes/definitions/notes.eval.dart'; 21 | import 'screens/modes/definitions/amenity.eval.dart'; 22 | import 'screens/modes/definitions/classic.eval.dart'; 23 | import 'widgets/map_button.eval.dart'; 24 | import 'widgets/poi_marker.eval.dart'; 25 | import 'widgets/entrance_markers.eval.dart'; 26 | import 'widgets/map.eval.dart'; 27 | import 'plugins/interface.eval.dart'; 28 | import 'plugins/preferences.eval.dart'; 29 | import 'plugins/providers.eval.dart'; 30 | import 'plugins/every_door_plugin.eval.dart'; 31 | import 'plugins/ext_overlay.eval.dart'; 32 | import 'plugins/events.eval.dart'; 33 | 34 | /// [EvalPlugin] for every_door 35 | class EveryDoorPlugin implements EvalPlugin { 36 | @override 37 | String get identifier => 'package:every_door'; 38 | 39 | @override 40 | void configureForCompile(BridgeDeclarationRegistry registry) { 41 | registry.defineBridgeClass($ElementKind.$declaration); 42 | registry.defineBridgeClass($ElementKindImpl.$declaration); 43 | registry.defineBridgeClass($TagMatcher.$declaration); 44 | registry.defineBridgeClass($ValueMatcher.$declaration); 45 | registry.defineBridgeClass($GeometryException.$declaration); 46 | registry.defineBridgeClass($Geometry.$declaration); 47 | registry.defineBridgeClass($Polygon.$declaration); 48 | registry.defineBridgeClass($Envelope.$declaration); 49 | registry.defineBridgeClass($MultiPolygon.$declaration); 50 | registry.defineBridgeClass($LineString.$declaration); 51 | registry.defineBridgeClass($PluginLocalizationsBranch.$declaration); 52 | registry.defineBridgeClass($LegendItem.$declaration); 53 | registry.defineBridgeClass($NamedColor.$declaration); 54 | registry.defineBridgeClass($PresetLabel.$declaration); 55 | registry.defineBridgeClass($LegendController.$declaration); 56 | registry.defineBridgeClass($MultiIcon.$declaration); 57 | registry.defineBridgeClass($AuthToken.$declaration); 58 | registry.defineBridgeClass($AuthToken$bridge.$declaration); 59 | registry.defineBridgeClass($UserDetails$bridge.$declaration); 60 | registry.defineBridgeClass($AuthException$bridge.$declaration); 61 | registry.defineBridgeClass($AuthProvider$bridge.$declaration); 62 | registry.defineBridgeClass($OAuth2AuthProvider$bridge.$declaration); 63 | registry.defineBridgeClass($AuthController.$declaration); 64 | registry.defineBridgeClass($Imagery.$declaration); 65 | registry.defineBridgeClass($BaseNote.$declaration); 66 | registry.defineBridgeClass($OsmId.$declaration); 67 | registry.defineBridgeClass($OsmMember.$declaration); 68 | registry.defineBridgeClass($OsmElement.$declaration); 69 | registry.defineBridgeClass($OsmChange.$declaration); 70 | registry.defineBridgeClass($PluginData.$declaration); 71 | registry.defineBridgeClass($Plugin.$declaration); 72 | registry.defineBridgeClass($PluginVersion.$declaration); 73 | registry.defineBridgeClass($PluginVersionRange.$declaration); 74 | registry.defineBridgeClass($EntrancesModeDefinition$bridge.$declaration); 75 | registry.defineBridgeClass($BaseModeDefinition.$declaration); 76 | registry.defineBridgeClass($MicromappingModeDefinition$bridge.$declaration); 77 | registry.defineBridgeClass($NotesModeDefinition$bridge.$declaration); 78 | registry.defineBridgeClass($AmenityModeDefinition$bridge.$declaration); 79 | registry.defineBridgeClass($ClassicModeDefinition$bridge.$declaration); 80 | registry.defineBridgeClass($MapButton.$declaration); 81 | registry.defineBridgeClass($NumberedMarker.$declaration); 82 | registry.defineBridgeClass($ColoredMarker.$declaration); 83 | registry.defineBridgeClass($SizedMarker.$declaration); 84 | registry.defineBridgeClass($BuildingMarker.$declaration); 85 | registry.defineBridgeClass($AddressMarker.$declaration); 86 | registry.defineBridgeClass($EntranceMarker.$declaration); 87 | registry.defineBridgeClass($IconMarker.$declaration); 88 | registry.defineBridgeClass($CustomMapController.$declaration); 89 | registry.defineBridgeClass($CustomMap.$declaration); 90 | registry.defineBridgeClass($EveryDoorApp.$declaration); 91 | registry.defineBridgeClass($PluginPreferences.$declaration); 92 | registry.defineBridgeClass($PluginProviders.$declaration); 93 | registry.defineBridgeClass($EveryDoorPlugin$bridge.$declaration); 94 | registry.defineBridgeClass($ExtOverlay.$declaration); 95 | registry.defineBridgeClass($PluginEvents.$declaration); 96 | registry.defineBridgeEnum($ImageryCategory.$declaration); 97 | registry.defineBridgeEnum($OsmElementType.$declaration); 98 | registry.defineBridgeEnum($IsMember.$declaration); 99 | } 100 | 101 | @override 102 | void configureForRuntime(Runtime runtime) { 103 | $ElementKind.configureForRuntime(runtime); 104 | $ElementKindImpl.configureForRuntime(runtime); 105 | $TagMatcher.configureForRuntime(runtime); 106 | $ValueMatcher.configureForRuntime(runtime); 107 | $GeometryException.configureForRuntime(runtime); 108 | $Geometry.configureForRuntime(runtime); 109 | $Polygon.configureForRuntime(runtime); 110 | $Envelope.configureForRuntime(runtime); 111 | $MultiPolygon.configureForRuntime(runtime); 112 | $LineString.configureForRuntime(runtime); 113 | $PluginLocalizationsBranch.configureForRuntime(runtime); 114 | $LegendItem.configureForRuntime(runtime); 115 | $NamedColor.configureForRuntime(runtime); 116 | $PresetLabel.configureForRuntime(runtime); 117 | $LegendController.configureForRuntime(runtime); 118 | $MultiIcon.configureForRuntime(runtime); 119 | $AuthToken.configureForRuntime(runtime); 120 | $AuthToken$bridge.configureForRuntime(runtime); 121 | $UserDetails$bridge.configureForRuntime(runtime); 122 | $AuthException$bridge.configureForRuntime(runtime); 123 | $AuthProvider$bridge.configureForRuntime(runtime); 124 | $OAuth2AuthProvider$bridge.configureForRuntime(runtime); 125 | $AuthController.configureForRuntime(runtime); 126 | $Imagery.configureForRuntime(runtime); 127 | $BaseNote.configureForRuntime(runtime); 128 | $OsmId.configureForRuntime(runtime); 129 | $OsmMember.configureForRuntime(runtime); 130 | $OsmElement.configureForRuntime(runtime); 131 | $OsmChange.configureForRuntime(runtime); 132 | $PluginData.configureForRuntime(runtime); 133 | $Plugin.configureForRuntime(runtime); 134 | $PluginVersion.configureForRuntime(runtime); 135 | $PluginVersionRange.configureForRuntime(runtime); 136 | $EntrancesModeDefinition$bridge.configureForRuntime(runtime); 137 | $BaseModeDefinition.configureForRuntime(runtime); 138 | $MicromappingModeDefinition$bridge.configureForRuntime(runtime); 139 | $NotesModeDefinition$bridge.configureForRuntime(runtime); 140 | $AmenityModeDefinition$bridge.configureForRuntime(runtime); 141 | $ClassicModeDefinition$bridge.configureForRuntime(runtime); 142 | $MapButton.configureForRuntime(runtime); 143 | $NumberedMarker.configureForRuntime(runtime); 144 | $ColoredMarker.configureForRuntime(runtime); 145 | $SizedMarker.configureForRuntime(runtime); 146 | $BuildingMarker.configureForRuntime(runtime); 147 | $AddressMarker.configureForRuntime(runtime); 148 | $EntranceMarker.configureForRuntime(runtime); 149 | $IconMarker.configureForRuntime(runtime); 150 | $CustomMapController.configureForRuntime(runtime); 151 | $CustomMap.configureForRuntime(runtime); 152 | $EveryDoorApp.configureForRuntime(runtime); 153 | $PluginPreferences.configureForRuntime(runtime); 154 | $PluginProviders.configureForRuntime(runtime); 155 | $EveryDoorPlugin$bridge.configureForRuntime(runtime); 156 | $ExtOverlay.configureForRuntime(runtime); 157 | $PluginEvents.configureForRuntime(runtime); 158 | $ImageryCategory.configureForRuntime(runtime); 159 | $OsmElementType.configureForRuntime(runtime); 160 | $IsMember.configureForRuntime(runtime); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /lib/cli/package.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | import 'dart:io'; 3 | import 'dart:isolate'; 4 | import 'dart:typed_data'; 5 | 6 | import 'package:archive/archive.dart'; 7 | import 'package:dart_eval/dart_eval.dart'; 8 | import 'package:dart_eval/dart_eval_bridge.dart'; 9 | import 'package:every_door_plugin/helpers/yaml_map.dart'; 10 | import 'package:every_door_plugin/plugins/bindings/every_door_eval.dart'; 11 | import 'package:flutter_eval/flutter_eval.dart'; 12 | import 'package:flutter_map_eval/flutter_map_eval.dart' as fme; 13 | import 'package:logging/logging.dart'; 14 | import 'package:path/path.dart' as p; 15 | import 'package:yaml/yaml.dart'; 16 | import 'package:yaml_writer/yaml_writer.dart'; 17 | 18 | class Locations { 19 | Directory? staticPluginRoot; 20 | Directory? codeRoot; 21 | Directory? distRoot; 22 | File? pubspecYaml; 23 | 24 | Locations() { 25 | staticPluginRoot = _findStaticPluginRoot(); 26 | pubspecYaml = _findPubspec(); 27 | codeRoot = _findCodeRoot(); 28 | if (codeRoot != null || staticPluginRoot != null) { 29 | distRoot = Directory( 30 | "${(pubspecYaml?.parent ?? codeRoot?.parent ?? staticPluginRoot!).path}/dist", 31 | ); 32 | } 33 | } 34 | 35 | bool get isValid => distRoot != null; 36 | 37 | Directory? _findStaticPluginRoot() { 38 | if (File("plugin/plugin.yaml").existsSync()) return Directory("plugin"); 39 | if (File("plugin.yaml").existsSync()) return Directory("."); 40 | if (Directory("plugin").existsSync()) return Directory("plugin"); 41 | return null; 42 | } 43 | 44 | Directory? _findCodeRoot() { 45 | final pubspecParent = pubspecYaml == null 46 | ? null 47 | : "${pubspecYaml!.parent.path}/lib"; 48 | if (pubspecParent != null && 49 | File("$pubspecParent/main.dart").existsSync()) { 50 | return Directory(pubspecParent); 51 | } 52 | 53 | if (File("lib/main.dart").existsSync()) return Directory("lib"); 54 | if (File("main.dart").existsSync()) return Directory("."); 55 | if (File("../lib/main.dart").existsSync()) return Directory("../lib"); 56 | return null; 57 | } 58 | 59 | File? _findPubspec() { 60 | for (final path in ['.', '..']) { 61 | final f = File("$path/pubspec.yaml"); 62 | if (f.existsSync()) return f; 63 | } 64 | return null; 65 | } 66 | 67 | File? get pluginYaml => staticPluginRoot == null 68 | ? null 69 | : File("${staticPluginRoot!.path}/plugin.yaml"); 70 | 71 | File dist(String id, String version) => 72 | File("${distRoot!.path}/${id}_$version.edp"); 73 | 74 | @override 75 | String toString() => 76 | 'Locations(pubspec="${pubspecYaml?.path}", plugin="${staticPluginRoot?.path}", code="${codeRoot?.path}")'; 77 | } 78 | 79 | class Packager { 80 | static final _logger = Logger("Packager"); 81 | 82 | Future> buildPluginYaml(Locations locations) async { 83 | Map result = {}; 84 | 85 | // First read the provided file. It has the lowest priority. 86 | final pluginYamlFile = locations.pluginYaml; 87 | if (pluginYamlFile != null && await pluginYamlFile.exists()) { 88 | final data = loadYaml(await pluginYamlFile.readAsString()); 89 | if (data is YamlMap) { 90 | result = data.toMap(); 91 | } 92 | } 93 | 94 | final pubspecFile = locations.pubspecYaml; 95 | if (pubspecFile != null && await pubspecFile.exists()) { 96 | final data = loadYaml(await pubspecFile.readAsString()); 97 | if (data is YamlMap) { 98 | final pubspec = data.toMap(); 99 | 100 | // Overwrite metadata values with every_door section. 101 | final edPart = pubspec['every_door']; 102 | if (edPart != null && edPart is Map) { 103 | for (final entry in edPart.entries) { 104 | result[entry.key] = entry.value; 105 | } 106 | } 107 | 108 | // And now copy the main fields, which have the highest priority. 109 | result['id'] = pubspec['name']; 110 | if (pubspec.containsKey('description')) { 111 | result['name'] = pubspec['description']; 112 | } 113 | final versionMatch = RegExp( 114 | r'^\d+\.\d+', 115 | ).matchAsPrefix(pubspec['version']); 116 | if (versionMatch != null) { 117 | result['version'] = versionMatch.group(0)!; 118 | } 119 | if (pubspec.containsKey('homepage')) { 120 | result['homepage'] = pubspec['homepage']; 121 | } 122 | } 123 | } 124 | 125 | return result; 126 | } 127 | 128 | Future loadBindings(Compiler compiler, String name) async { 129 | final packagePath = 'package:every_door_plugin/bindings/$name.json'; 130 | final packageUri = await Isolate.resolvePackageUri(Uri.parse(packagePath)); 131 | if (packageUri == null) { 132 | throw FileSystemException("Cannot find $packagePath"); 133 | } 134 | final contents = await File(p.fromUri(packageUri)).readAsString(); 135 | final data = json.decode(contents) as Map; 136 | 137 | for (final $class in (data['classes'] as List).cast()) { 138 | compiler.defineBridgeClass(BridgeClassDef.fromJson($class.cast())); 139 | } 140 | for (final $enum in (data['enums'] as List).cast()) { 141 | compiler.defineBridgeEnum(BridgeEnumDef.fromJson($enum.cast())); 142 | } 143 | for (final $source in (data['sources'] as List).cast()) { 144 | compiler.addSource(DartSource($source['uri'], $source['source'])); 145 | } 146 | for (final $function in (data['functions'] as List).cast()) { 147 | compiler.defineBridgeTopLevelFunction( 148 | BridgeFunctionDeclaration.fromJson($function.cast()), 149 | ); 150 | } 151 | } 152 | 153 | Future compileCode(Locations locations) async { 154 | String packageName; 155 | final pubspecData = loadYaml(await locations.pubspecYaml!.readAsString()); 156 | if (pubspecData is! YamlMap) { 157 | throw ArgumentError("Could not read pubspec.yaml"); 158 | } 159 | packageName = pubspecData.toMap()['name']; 160 | 161 | final compiler = Compiler(); 162 | compiler.addPlugin(flutterEvalPlugin); 163 | for (final p in fme.plugins) { 164 | compiler.addPlugin(p); 165 | } 166 | compiler.addPlugin(EveryDoorPlugin()); 167 | // await loadBindings(compiler, 'flutter_eval'); 168 | 169 | Map addFiles(Directory dir) { 170 | final result = {}; 171 | if (!dir.existsSync()) return result; 172 | for (final file in dir.listSync()) { 173 | if (file is File && file.path.endsWith('.dart')) { 174 | String fileData = file.readAsStringSync(); 175 | fileData = fileData.replaceAll('package:every_door_plugin/', 'package:every_door/'); 176 | final rel = p 177 | .relative(file.path, from: locations.codeRoot!.path) 178 | .replaceAll('\\', '/'); 179 | result[rel] = fileData; 180 | } else if (file is Directory) { 181 | result.addAll(addFiles(file)); 182 | } 183 | } 184 | return result; 185 | } 186 | 187 | final data = {packageName: addFiles(locations.codeRoot!)}; 188 | final program = compiler.compile(data); 189 | return program.write(); 190 | } 191 | 192 | Future run() async { 193 | final locations = Locations(); 194 | if (!locations.isValid) { 195 | throw ArgumentError("Cannot find the plugin source"); 196 | } 197 | 198 | final pluginData = await buildPluginYaml(locations); 199 | _logger.info('Found plugin "${pluginData['id']}" v${pluginData['version']}'); 200 | 201 | final dist = locations.dist(pluginData['id'], pluginData['version']); 202 | if (dist.existsSync()) { 203 | _logger.info("Overwriting file ${dist.path}"); 204 | await dist.delete(); 205 | } 206 | 207 | final zipOutput = OutputFileStream(dist.path); 208 | final zip = ZipEncoder(); 209 | zip.startEncode(zipOutput, level: DeflateLevel.defaultCompression); 210 | 211 | // Write the plugin.yaml. 212 | zip.add(ArchiveFile.string("plugin.yaml", YamlWriter().write(pluginData))); 213 | 214 | // Write the compiled code. 215 | if (locations.codeRoot != null && locations.pubspecYaml != null) { 216 | zip.add(ArchiveFile.bytes("plugin.evc", await compileCode(locations))); 217 | } 218 | 219 | // Write the rest of static files. 220 | if (locations.staticPluginRoot != null) { 221 | for (final f in locations.staticPluginRoot!.listSync(recursive: true)) { 222 | if (f is File) { 223 | if (p.isWithin(dist.parent.path, f.path)) continue; 224 | final path = p.relative(f.path, from: locations.staticPluginRoot!.path); 225 | if (path == 'plugin.yaml') continue; 226 | _logger.info('Adding $path'); 227 | zip.add(ArchiveFile.bytes(path, await f.readAsBytes())); 228 | } 229 | } 230 | } 231 | 232 | zip.endEncode(); 233 | } 234 | } -------------------------------------------------------------------------------- /lib/plugins/bindings/models/note.eval.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers 2 | import 'package:dart_eval/dart_eval_bridge.dart'; 3 | import 'package:every_door_plugin/models/note.dart'; 4 | import 'package:dart_eval/stdlib/core.dart'; 5 | import 'package:flutter_map_eval/latlong2/latlong2_eval.dart'; 6 | 7 | /// dart_eval wrapper binding for [BaseNote] 8 | class $BaseNote implements $Instance { 9 | /// Configure this class for use in a [Runtime] 10 | static void configureForRuntime(Runtime runtime) { 11 | runtime.registerBridgeFunc( 12 | 'package:every_door/models/note.dart', 13 | 'BaseNote.', 14 | $BaseNote.$new, 15 | ); 16 | 17 | runtime.registerBridgeFunc( 18 | 'package:every_door/models/note.dart', 19 | 'BaseNote.fromJson', 20 | $BaseNote.$fromJson, 21 | ); 22 | } 23 | 24 | /// Compile-time type specification of [$BaseNote] 25 | static const $spec = BridgeTypeSpec( 26 | 'package:every_door/models/note.dart', 27 | 'BaseNote', 28 | ); 29 | 30 | /// Compile-time type declaration of [$BaseNote] 31 | static const $type = BridgeTypeRef($spec); 32 | 33 | /// Compile-time class declaration of [$BaseNote] 34 | static const $declaration = BridgeClassDef( 35 | BridgeClassType($type), 36 | constructors: { 37 | '': BridgeConstructorDef( 38 | BridgeFunctionDef( 39 | returns: BridgeTypeAnnotation($type), 40 | namedParams: [ 41 | BridgeParameter( 42 | 'location', 43 | BridgeTypeAnnotation( 44 | BridgeTypeRef( 45 | BridgeTypeSpec('package:latlong2/latlong.dart', 'LatLng'), 46 | [], 47 | ), 48 | ), 49 | false, 50 | ), 51 | 52 | BridgeParameter( 53 | 'id', 54 | BridgeTypeAnnotation( 55 | BridgeTypeRef(CoreTypes.int, []), 56 | nullable: true, 57 | ), 58 | true, 59 | ), 60 | 61 | BridgeParameter( 62 | 'type', 63 | BridgeTypeAnnotation( 64 | BridgeTypeRef(CoreTypes.int, []), 65 | nullable: true, 66 | ), 67 | false, 68 | ), 69 | 70 | BridgeParameter( 71 | 'created', 72 | BridgeTypeAnnotation( 73 | BridgeTypeRef(CoreTypes.dateTime, []), 74 | nullable: true, 75 | ), 76 | true, 77 | ), 78 | 79 | BridgeParameter( 80 | 'deleting', 81 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 82 | true, 83 | ), 84 | ], 85 | params: [], 86 | ), 87 | isFactory: false, 88 | ), 89 | 90 | 'fromJson': BridgeConstructorDef( 91 | BridgeFunctionDef( 92 | returns: BridgeTypeAnnotation($type), 93 | namedParams: [], 94 | params: [ 95 | BridgeParameter( 96 | 'data', 97 | BridgeTypeAnnotation( 98 | BridgeTypeRef(CoreTypes.map, [ 99 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 100 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.dynamic)), 101 | ]), 102 | ), 103 | false, 104 | ), 105 | ], 106 | ), 107 | isFactory: true, 108 | ), 109 | }, 110 | 111 | methods: { 112 | 'revert': BridgeMethodDef( 113 | BridgeFunctionDef( 114 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 115 | namedParams: [], 116 | params: [], 117 | ), 118 | ), 119 | 120 | 'toJson': BridgeMethodDef( 121 | BridgeFunctionDef( 122 | returns: BridgeTypeAnnotation( 123 | BridgeTypeRef(CoreTypes.map, [ 124 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 125 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.dynamic)), 126 | ]), 127 | ), 128 | namedParams: [], 129 | params: [], 130 | ), 131 | ), 132 | }, 133 | getters: { 134 | 'isChanged': BridgeMethodDef( 135 | BridgeFunctionDef( 136 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 137 | namedParams: [], 138 | params: [], 139 | ), 140 | ), 141 | 142 | 'isNew': BridgeMethodDef( 143 | BridgeFunctionDef( 144 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 145 | namedParams: [], 146 | params: [], 147 | ), 148 | ), 149 | }, 150 | setters: {}, 151 | fields: { 152 | 'id': BridgeFieldDef( 153 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int, []), nullable: true), 154 | isStatic: false, 155 | ), 156 | 157 | 'type': BridgeFieldDef( 158 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int, []), nullable: true), 159 | isStatic: false, 160 | ), 161 | 162 | 'location': BridgeFieldDef( 163 | BridgeTypeAnnotation( 164 | BridgeTypeRef( 165 | BridgeTypeSpec('package:latlong2/latlong.dart', 'LatLng'), 166 | [], 167 | ), 168 | ), 169 | isStatic: false, 170 | ), 171 | 172 | 'created': BridgeFieldDef( 173 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.dateTime, [])), 174 | isStatic: false, 175 | ), 176 | 177 | 'deleting': BridgeFieldDef( 178 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 179 | isStatic: false, 180 | ), 181 | }, 182 | wrap: true, 183 | bridge: false, 184 | ); 185 | 186 | /// Wrapper for the [BaseNote.new] constructor 187 | static $Value? $new(Runtime runtime, $Value? thisValue, List<$Value?> args) { 188 | return $BaseNote.wrap( 189 | BaseNote( 190 | location: args[0]!.$value, 191 | id: args[1]?.$value, 192 | type: args[2]!.$value, 193 | created: args[3]?.$value, 194 | deleting: args[4]?.$value ?? false, 195 | ), 196 | ); 197 | } 198 | 199 | /// Wrapper for the [BaseNote.fromJson] constructor 200 | static $Value? $fromJson( 201 | Runtime runtime, 202 | $Value? thisValue, 203 | List<$Value?> args, 204 | ) { 205 | return $BaseNote.wrap(BaseNote.fromJson((args[0]!.$reified as Map).cast())); 206 | } 207 | 208 | final $Instance _superclass; 209 | 210 | @override 211 | final BaseNote $value; 212 | 213 | @override 214 | BaseNote get $reified => $value; 215 | 216 | /// Wrap a [BaseNote] in a [$BaseNote] 217 | $BaseNote.wrap(this.$value) : _superclass = $Object($value); 218 | 219 | @override 220 | int $getRuntimeType(Runtime runtime) => runtime.lookupType($spec); 221 | 222 | @override 223 | $Value? $getProperty(Runtime runtime, String identifier) { 224 | switch (identifier) { 225 | case 'id': 226 | final _id = $value.id; 227 | return _id == null ? const $null() : $int(_id); 228 | 229 | case 'type': 230 | final _type = $value.type; 231 | return _type == null ? const $null() : $int(_type); 232 | 233 | case 'location': 234 | final _location = $value.location; 235 | return $LatLng.wrap(_location); 236 | 237 | case 'created': 238 | final _created = $value.created; 239 | return $DateTime.wrap(_created); 240 | 241 | case 'deleting': 242 | final _deleting = $value.deleting; 243 | return $bool(_deleting); 244 | 245 | case 'isChanged': 246 | final _isChanged = $value.isChanged; 247 | return $bool(_isChanged); 248 | 249 | case 'isNew': 250 | final _isNew = $value.isNew; 251 | return $bool(_isNew); 252 | case 'revert': 253 | return __revert; 254 | 255 | case 'toJson': 256 | return __toJson; 257 | } 258 | return _superclass.$getProperty(runtime, identifier); 259 | } 260 | 261 | static const $Function __revert = $Function(_revert); 262 | static $Value? _revert(Runtime runtime, $Value? target, List<$Value?> args) { 263 | final self = target! as $BaseNote; 264 | final result = self.$value.revert(); 265 | return $bool(result); 266 | } 267 | 268 | static const $Function __toJson = $Function(_toJson); 269 | static $Value? _toJson(Runtime runtime, $Value? target, List<$Value?> args) { 270 | final self = target! as $BaseNote; 271 | final result = self.$value.toJson(); 272 | return $Map.wrap(result); 273 | } 274 | 275 | @override 276 | void $setProperty(Runtime runtime, String identifier, $Value value) { 277 | switch (identifier) { 278 | case 'id': 279 | $value.id = value.$value; 280 | return; 281 | 282 | case 'deleting': 283 | $value.deleting = value.$value; 284 | return; 285 | } 286 | return _superclass.$setProperty(runtime, identifier, value); 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /lib/models/amenity.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:every_door_plugin/helpers/tags/main_key.dart'; 4 | import 'package:every_door_plugin/models/osm_element.dart'; 5 | import 'package:flutter/foundation.dart'; 6 | import 'package:latlong2/latlong.dart'; 7 | 8 | class OsmChange extends ChangeNotifier implements Comparable { 9 | static const kCheckedKey = 'check_date'; 10 | 11 | final OsmElement? element; 12 | 13 | Map newTags; 14 | LatLng? newLocation; 15 | List? newNodes; // WARNING: Not stored to the database! 16 | bool _deleted; 17 | String? error; 18 | final String databaseId; 19 | String? _mainKey; 20 | Map? _fullTagsCache; 21 | DateTime updated; 22 | int? newId; // Not stored: used only during uploading. 23 | 24 | OsmChange(OsmElement element, 25 | {Map? newTags, 26 | this.newLocation, 27 | bool hardDeleted = false, 28 | this.error, 29 | DateTime? updated, 30 | this.newNodes, 31 | String? databaseId}) 32 | : newTags = newTags ?? {}, 33 | _deleted = hardDeleted, 34 | updated = updated ?? DateTime.now(), 35 | // ignore: prefer_initializing_formals 36 | element = element, // Force non-null initialization 37 | databaseId = databaseId ?? element.id.toString() { 38 | _updateMainKey(); 39 | } 40 | 41 | OsmChange.create({ 42 | required Map tags, 43 | required LatLng location, 44 | DateTime? updated, 45 | String? databaseId, 46 | this.error, 47 | this.newId, 48 | }) : newTags = Map.of(tags), 49 | newLocation = location, 50 | element = null, 51 | _deleted = false, 52 | updated = updated ?? DateTime.now(), 53 | databaseId = databaseId ?? '' { 54 | _updateMainKey(); 55 | } 56 | 57 | OsmChange copy() { 58 | if (element == null) { 59 | return OsmChange.create( 60 | tags: Map.of(newTags.cast()), 61 | location: newLocation!, 62 | error: error, 63 | updated: updated, 64 | databaseId: databaseId, 65 | newId: newId, 66 | ); 67 | } 68 | 69 | return OsmChange( 70 | element!, 71 | newTags: Map.of(newTags), 72 | newLocation: newLocation, 73 | hardDeleted: _deleted, 74 | error: error, 75 | updated: updated, 76 | newNodes: newNodes, 77 | databaseId: databaseId, 78 | ); 79 | } 80 | 81 | // Location and modification 82 | LatLng get location => newLocation ?? element!.center!; 83 | set location(LatLng loc) { 84 | newLocation = loc; 85 | notifyListeners(); 86 | } 87 | 88 | OsmId get id { 89 | if (element == null) throw StateError('Trying to get id for a new amenity'); 90 | return element!.id; 91 | } 92 | 93 | bool get deleted => 94 | _deleted || 95 | (_mainKey?.startsWith(kDeleted) ?? false) || 96 | (_mainKey?.startsWith(kBuildingDeleted) ?? false); 97 | bool get hardDeleted => _deleted; 98 | bool get isModified => 99 | newTags.isNotEmpty || 100 | newLocation != null || 101 | newNodes != null || 102 | hardDeleted; 103 | bool get isConfirmed => 104 | !deleted && (newTags.length == 1 && newTags.keys.first == kCheckedKey); 105 | bool get isNew => element == null; 106 | bool get isArea => element?.isArea ?? false; 107 | bool get isPoint => element?.isPoint ?? true; 108 | bool get canDelete => 109 | (element?.isPoint ?? true) && 110 | (element == null || element?.isMember == IsMember.no); 111 | bool get canMove => 112 | (element?.isPoint ?? true) && (element?.isMember != IsMember.way); 113 | String? get mainKey => _mainKey; 114 | 115 | void revert() { 116 | // Cannot revert a new object 117 | if (isNew) return; 118 | 119 | newTags.clear(); 120 | newLocation = null; 121 | _updateMainKey(); 122 | notifyListeners(); 123 | } 124 | 125 | // Tags management 126 | String? operator [](String k) => 127 | newTags.containsKey(k) ? newTags[k] : element?.tags[k]; 128 | 129 | void operator []=(String k, String? v) { 130 | if (v == null || v.isEmpty) { 131 | removeTag(k); 132 | } else if (element == null || element!.tags[k] != v) { 133 | // Silently cut the value. 134 | if (v.length > 255) v = v.substring(0, 255); 135 | newTags[k] = v; 136 | } else if (newTags.containsKey(k)) { 137 | newTags.remove(k); 138 | } 139 | _updateMainKey(); 140 | notifyListeners(); 141 | } 142 | 143 | void removeTag(String key) { 144 | if (element != null && element!.tags.containsKey(key)) { 145 | newTags[key] = null; 146 | } else if (newTags[key] != null) { 147 | newTags.remove(key); 148 | } else { 149 | return; 150 | } 151 | _updateMainKey(); 152 | notifyListeners(); 153 | } 154 | 155 | void undoTagChange(String key) { 156 | if (newTags.containsKey(key)) { 157 | newTags.remove(key); 158 | _updateMainKey(); 159 | notifyListeners(); 160 | } 161 | } 162 | 163 | bool hasTag(String key) => this[key] != null; 164 | bool changedTag(String key) => newTags.containsKey(key); 165 | 166 | void _updateMainKey() { 167 | _fullTagsCache = null; 168 | _mainKey = getMainKey(getFullTags()); 169 | } 170 | 171 | int calculateAge(String? value) => DateTime.now() 172 | .difference( 173 | DateTime.tryParse(value ?? '2020-01-01') ?? DateTime(2020, 1, 1)) 174 | .inDays; 175 | 176 | // Check date management. 177 | int get age => calculateAge(this[kCheckedKey]); 178 | int get baseAge => calculateAge(element?.tags[kCheckedKey]); 179 | bool get isOld => isCountedOld(age); 180 | bool get wasOld => 181 | !isNew && isCountedOld(calculateAge(element?.tags[kCheckedKey])); 182 | bool get isCheckedToday => age <= 1; 183 | 184 | bool isCountedOld(int age) => false; 185 | 186 | void check() { 187 | } 188 | 189 | void uncheck() { 190 | } 191 | 192 | void toggleCheck() { 193 | } 194 | 195 | set deleted(bool value) { 196 | } 197 | 198 | factory OsmChange.fromJson(Map data) { 199 | return OsmChange.create(tags: {}, location: LatLng(0, 0)); 200 | } 201 | 202 | Map toJson() => {}; 203 | 204 | /// Constructs a new element from this change after the object has been uploaded. 205 | /// Or for uploading. 206 | OsmElement toElement({int? newId, int? newVersion}) { 207 | throw UnimplementedError(); 208 | } 209 | 210 | /// Updates the underlying [OsmElement]. 211 | OsmChange mergeNewElement(OsmElement newElement) { 212 | throw UnimplementedError(); 213 | } 214 | 215 | // Helper methods 216 | 217 | bool get isDisused => false; 218 | 219 | void togglePrefix(String prefix) { 220 | } 221 | 222 | void toggleDisused() { 223 | } 224 | 225 | String? get name => getAnyName() ?? this['operator'] ?? this['brand']; 226 | 227 | String? getAnyName() { 228 | return null; 229 | } 230 | 231 | String? getLocalName(Locale locale) => this['name']; 232 | 233 | String? getContact(String key) => this[key]; 234 | 235 | void setContact(String key, String value) { 236 | } 237 | 238 | void removeOpeningHoursSigned() { 239 | } 240 | 241 | bool get hasPayment => false; 242 | 243 | bool get acceptsCards => false; 244 | 245 | bool get cashOnly => false; 246 | 247 | bool get hasWebsite => false; 248 | 249 | String? get descriptiveTag => mainKey; 250 | 251 | String get typeAndName => 'type'; 252 | 253 | String? get address => null; 254 | 255 | bool isFixmeNote() => false; 256 | 257 | // Helper methods 258 | 259 | /// Returns a map with complete object tags. All changes are applied, 260 | /// deleted tags are removed. Set `clearDisused` to `true` to remove 261 | /// the `disused:` prefix from the main tag. 262 | Map getFullTags([bool clearDisused = false]) => {}; 263 | 264 | @override 265 | bool operator ==(other) { 266 | if (other is! OsmChange) return false; 267 | if (element != other.element) return false; 268 | if (databaseId != other.databaseId) return false; 269 | if (_deleted != other._deleted) return false; 270 | if (newLocation != other.newLocation) return false; 271 | if (!mapEquals(newTags, other.newTags)) return false; 272 | return true; 273 | } 274 | 275 | @override 276 | int get hashCode => databaseId.hashCode; 277 | 278 | @override 279 | int compareTo(other) { 280 | const kTypeOrder = { 281 | OsmElementType.node: 0, 282 | OsmElementType.way: 1, 283 | OsmElementType.relation: 2, 284 | }; 285 | 286 | if (other is! OsmChange) 287 | throw ArgumentError('OsmChange can be compared only to another change'); 288 | // Order for uploading: create (n), modify (nwr), delete(rwn). 289 | if (isNew) { 290 | return other.isNew ? 0 : -1; 291 | } else if (isModified && !hardDeleted) { 292 | if (other.isNew) return 1; 293 | if (other.hardDeleted) return -1; 294 | return kTypeOrder[id.type]!.compareTo(kTypeOrder[other.id.type]!); 295 | } else { 296 | // deleted 297 | if (!other.hardDeleted) return 1; 298 | return kTypeOrder[other.id.type]!.compareTo(kTypeOrder[id.type]!); 299 | } 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /lib/plugins/bindings/helpers/multi_icon.eval.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers 2 | import 'package:dart_eval/dart_eval_bridge.dart'; 3 | import 'package:every_door_plugin/helpers/multi_icon.dart'; 4 | import 'package:dart_eval/stdlib/core.dart'; 5 | import 'package:flutter_eval/widgets.dart'; 6 | 7 | /// dart_eval wrapper binding for [MultiIcon] 8 | class $MultiIcon implements $Instance { 9 | /// Configure this class for use in a [Runtime] 10 | static void configureForRuntime(Runtime runtime) { 11 | runtime.registerBridgeFunc( 12 | 'package:every_door/helpers/multi_icon.dart', 13 | 'MultiIcon.', 14 | $MultiIcon.$new, 15 | ); 16 | } 17 | 18 | /// Compile-time type specification of [$MultiIcon] 19 | static const $spec = BridgeTypeSpec( 20 | 'package:every_door/helpers/multi_icon.dart', 21 | 'MultiIcon', 22 | ); 23 | 24 | /// Compile-time type declaration of [$MultiIcon] 25 | static const $type = BridgeTypeRef($spec); 26 | 27 | /// Compile-time class declaration of [$MultiIcon] 28 | static const $declaration = BridgeClassDef( 29 | BridgeClassType($type), 30 | constructors: { 31 | '': BridgeConstructorDef( 32 | BridgeFunctionDef( 33 | returns: BridgeTypeAnnotation($type), 34 | namedParams: [ 35 | BridgeParameter( 36 | 'fontIcon', 37 | BridgeTypeAnnotation( 38 | BridgeTypeRef( 39 | BridgeTypeSpec( 40 | 'package:flutter/src/widgets/icon_data.dart', 41 | 'IconData', 42 | ), 43 | [], 44 | ), 45 | nullable: true, 46 | ), 47 | true, 48 | ), 49 | 50 | BridgeParameter( 51 | 'emoji', 52 | BridgeTypeAnnotation( 53 | BridgeTypeRef(CoreTypes.string, []), 54 | nullable: true, 55 | ), 56 | true, 57 | ), 58 | 59 | BridgeParameter( 60 | 'imageData', 61 | BridgeTypeAnnotation( 62 | BridgeTypeRef(TypedDataTypes.uint8List, []), 63 | nullable: true, 64 | ), 65 | true, 66 | ), 67 | 68 | BridgeParameter( 69 | 'svgData', 70 | BridgeTypeAnnotation( 71 | BridgeTypeRef(TypedDataTypes.uint8List, []), 72 | nullable: true, 73 | ), 74 | true, 75 | ), 76 | 77 | BridgeParameter( 78 | 'siData', 79 | BridgeTypeAnnotation( 80 | BridgeTypeRef(TypedDataTypes.uint8List, []), 81 | nullable: true, 82 | ), 83 | true, 84 | ), 85 | 86 | BridgeParameter( 87 | 'imageUrl', 88 | BridgeTypeAnnotation( 89 | BridgeTypeRef(CoreTypes.string, []), 90 | nullable: true, 91 | ), 92 | true, 93 | ), 94 | 95 | BridgeParameter( 96 | 'asset', 97 | BridgeTypeAnnotation( 98 | BridgeTypeRef(CoreTypes.string, []), 99 | nullable: true, 100 | ), 101 | true, 102 | ), 103 | 104 | BridgeParameter( 105 | 'tooltip', 106 | BridgeTypeAnnotation( 107 | BridgeTypeRef(CoreTypes.string, []), 108 | nullable: true, 109 | ), 110 | true, 111 | ), 112 | ], 113 | params: [], 114 | ), 115 | isFactory: false, 116 | ), 117 | }, 118 | 119 | methods: { 120 | 'withTooltip': BridgeMethodDef( 121 | BridgeFunctionDef( 122 | returns: BridgeTypeAnnotation( 123 | BridgeTypeRef( 124 | BridgeTypeSpec( 125 | 'package:every_door/helpers/multi_icon.dart', 126 | 'MultiIcon', 127 | ), 128 | [], 129 | ), 130 | ), 131 | namedParams: [], 132 | params: [ 133 | BridgeParameter( 134 | 'tooltip', 135 | BridgeTypeAnnotation( 136 | BridgeTypeRef(CoreTypes.string, []), 137 | nullable: true, 138 | ), 139 | false, 140 | ), 141 | ], 142 | ), 143 | ), 144 | 145 | 'getWidget': BridgeMethodDef( 146 | BridgeFunctionDef( 147 | returns: BridgeTypeAnnotation( 148 | BridgeTypeRef( 149 | BridgeTypeSpec( 150 | 'package:flutter/src/widgets/framework.dart', 151 | 'Widget', 152 | ), 153 | [], 154 | ), 155 | ), 156 | namedParams: [ 157 | BridgeParameter( 158 | 'context', 159 | BridgeTypeAnnotation( 160 | BridgeTypeRef( 161 | BridgeTypeSpec( 162 | 'package:flutter/src/widgets/framework.dart', 163 | 'BuildContext', 164 | ), 165 | [], 166 | ), 167 | nullable: true, 168 | ), 169 | true, 170 | ), 171 | 172 | BridgeParameter( 173 | 'size', 174 | BridgeTypeAnnotation( 175 | BridgeTypeRef(CoreTypes.double, []), 176 | nullable: true, 177 | ), 178 | true, 179 | ), 180 | 181 | BridgeParameter( 182 | 'color', 183 | BridgeTypeAnnotation( 184 | BridgeTypeRef(BridgeTypeSpec('dart:ui', 'Color'), []), 185 | nullable: true, 186 | ), 187 | true, 188 | ), 189 | 190 | BridgeParameter( 191 | 'semanticLabel', 192 | BridgeTypeAnnotation( 193 | BridgeTypeRef(CoreTypes.string, []), 194 | nullable: true, 195 | ), 196 | true, 197 | ), 198 | 199 | BridgeParameter( 200 | 'icon', 201 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 202 | true, 203 | ), 204 | 205 | BridgeParameter( 206 | 'fixedSize', 207 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 208 | true, 209 | ), 210 | ], 211 | params: [], 212 | ), 213 | ), 214 | }, 215 | getters: {}, 216 | setters: {}, 217 | fields: { 218 | 'tooltip': BridgeFieldDef( 219 | BridgeTypeAnnotation( 220 | BridgeTypeRef(CoreTypes.string, []), 221 | nullable: true, 222 | ), 223 | isStatic: false, 224 | ), 225 | }, 226 | wrap: true, 227 | bridge: false, 228 | ); 229 | 230 | /// Wrapper for the [MultiIcon.new] constructor 231 | static $Value? $new(Runtime runtime, $Value? thisValue, List<$Value?> args) { 232 | return $MultiIcon.wrap( 233 | MultiIcon( 234 | fontIcon: args[0]?.$value, 235 | emoji: args[1]?.$value, 236 | imageData: args[2]?.$value, 237 | svgData: args[3]?.$value, 238 | siData: args[4]?.$value, 239 | imageUrl: args[5]?.$value, 240 | asset: args[6]?.$value, 241 | tooltip: args[7]?.$value, 242 | ), 243 | ); 244 | } 245 | 246 | final $Instance _superclass; 247 | 248 | @override 249 | final MultiIcon $value; 250 | 251 | @override 252 | MultiIcon get $reified => $value; 253 | 254 | /// Wrap a [MultiIcon] in a [$MultiIcon] 255 | $MultiIcon.wrap(this.$value) : _superclass = $Object($value); 256 | 257 | @override 258 | int $getRuntimeType(Runtime runtime) => runtime.lookupType($spec); 259 | 260 | @override 261 | $Value? $getProperty(Runtime runtime, String identifier) { 262 | switch (identifier) { 263 | case 'tooltip': 264 | final _tooltip = $value.tooltip; 265 | return _tooltip == null ? const $null() : $String(_tooltip); 266 | case 'withTooltip': 267 | return __withTooltip; 268 | 269 | case 'getWidget': 270 | return __getWidget; 271 | } 272 | return _superclass.$getProperty(runtime, identifier); 273 | } 274 | 275 | static const $Function __withTooltip = $Function(_withTooltip); 276 | static $Value? _withTooltip( 277 | Runtime runtime, 278 | $Value? target, 279 | List<$Value?> args, 280 | ) { 281 | final self = target! as $MultiIcon; 282 | final result = self.$value.withTooltip(args[0]!.$value); 283 | return $MultiIcon.wrap(result); 284 | } 285 | 286 | static const $Function __getWidget = $Function(_getWidget); 287 | static $Value? _getWidget( 288 | Runtime runtime, 289 | $Value? target, 290 | List<$Value?> args, 291 | ) { 292 | final self = target! as $MultiIcon; 293 | final result = self.$value.getWidget( 294 | context: args[0]?.$value, 295 | size: args[1]?.$value, 296 | color: args[2]?.$value, 297 | semanticLabel: args[3]?.$value, 298 | icon: args[4]?.$value ?? true, 299 | fixedSize: args[5]?.$value ?? true, 300 | ); 301 | return $Widget.wrap(result); 302 | } 303 | 304 | @override 305 | void $setProperty(Runtime runtime, String identifier, $Value value) { 306 | return _superclass.$setProperty(runtime, identifier, value); 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /lib/plugins/bindings/models/imagery.eval.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers 2 | import 'package:dart_eval/dart_eval_bridge.dart'; 3 | import 'package:every_door_plugin/models/imagery.dart'; 4 | import 'package:dart_eval/stdlib/core.dart'; 5 | import 'package:every_door_plugin/plugins/bindings/helpers/multi_icon.eval.dart'; 6 | import 'package:flutter_eval/widgets.dart'; 7 | 8 | /// dart_eval enum wrapper binding for [ImageryCategory] 9 | class $ImageryCategory implements $Instance { 10 | /// Configure this enum for use in a [Runtime] 11 | static void configureForRuntime(Runtime runtime) { 12 | runtime.registerBridgeEnumValues( 13 | 'package:every_door/models/imagery.dart', 14 | 'ImageryCategory', 15 | $ImageryCategory._$values, 16 | ); 17 | 18 | runtime.registerBridgeFunc( 19 | 'package:every_door/models/imagery.dart', 20 | 'ImageryCategory.values*g', 21 | $ImageryCategory.$values, 22 | ); 23 | } 24 | 25 | /// Compile-time type specification of [$ImageryCategory] 26 | static const $spec = BridgeTypeSpec( 27 | 'package:every_door/models/imagery.dart', 28 | 'ImageryCategory', 29 | ); 30 | 31 | /// Compile-time type declaration of [$ImageryCategory] 32 | static const $type = BridgeTypeRef($spec); 33 | 34 | /// Compile-time class declaration of [$ImageryCategory] 35 | static const $declaration = BridgeEnumDef( 36 | $type, 37 | 38 | values: ['photo', 'map', 'other'], 39 | 40 | methods: {}, 41 | getters: {}, 42 | setters: {}, 43 | fields: {}, 44 | ); 45 | 46 | static final _$values = { 47 | 'photo': $ImageryCategory.wrap(ImageryCategory.photo), 48 | 'map': $ImageryCategory.wrap(ImageryCategory.map), 49 | 'other': $ImageryCategory.wrap(ImageryCategory.other), 50 | }; 51 | 52 | /// Wrapper for the [ImageryCategory.values] getter 53 | static $Value? $values(Runtime runtime, $Value? target, List<$Value?> args) { 54 | final value = ImageryCategory.values; 55 | return $List.view(value, (e) => $ImageryCategory.wrap(e)); 56 | } 57 | 58 | final $Instance _superclass; 59 | 60 | @override 61 | final ImageryCategory $value; 62 | 63 | @override 64 | ImageryCategory get $reified => $value; 65 | 66 | /// Wrap a [ImageryCategory] in a [$ImageryCategory] 67 | $ImageryCategory.wrap(this.$value) : _superclass = $Object($value); 68 | 69 | @override 70 | int $getRuntimeType(Runtime runtime) => runtime.lookupType($spec); 71 | 72 | @override 73 | $Value? $getProperty(Runtime runtime, String identifier) { 74 | return _superclass.$getProperty(runtime, identifier); 75 | } 76 | 77 | @override 78 | void $setProperty(Runtime runtime, String identifier, $Value value) { 79 | return _superclass.$setProperty(runtime, identifier, value); 80 | } 81 | } 82 | 83 | /// dart_eval wrapper binding for [Imagery] 84 | class $Imagery implements $Instance { 85 | /// Configure this class for use in a [Runtime] 86 | static void configureForRuntime(Runtime runtime) {} 87 | 88 | /// Compile-time type specification of [$Imagery] 89 | static const $spec = BridgeTypeSpec( 90 | 'package:every_door/models/imagery.dart', 91 | 'Imagery', 92 | ); 93 | 94 | /// Compile-time type declaration of [$Imagery] 95 | static const $type = BridgeTypeRef($spec); 96 | 97 | /// Compile-time class declaration of [$Imagery] 98 | static const $declaration = BridgeClassDef( 99 | BridgeClassType($type, isAbstract: true), 100 | constructors: { 101 | '': BridgeConstructorDef( 102 | BridgeFunctionDef( 103 | returns: BridgeTypeAnnotation($type), 104 | namedParams: [ 105 | BridgeParameter( 106 | 'id', 107 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 108 | false, 109 | ), 110 | 111 | BridgeParameter( 112 | 'category', 113 | BridgeTypeAnnotation( 114 | BridgeTypeRef( 115 | BridgeTypeSpec( 116 | 'package:every_door/models/imagery.dart', 117 | 'ImageryCategory', 118 | ), 119 | [], 120 | ), 121 | nullable: true, 122 | ), 123 | true, 124 | ), 125 | 126 | BridgeParameter( 127 | 'name', 128 | BridgeTypeAnnotation( 129 | BridgeTypeRef(CoreTypes.string, []), 130 | nullable: true, 131 | ), 132 | true, 133 | ), 134 | 135 | BridgeParameter( 136 | 'icon', 137 | BridgeTypeAnnotation( 138 | BridgeTypeRef( 139 | BridgeTypeSpec( 140 | 'package:every_door/helpers/multi_icon.dart', 141 | 'MultiIcon', 142 | ), 143 | [], 144 | ), 145 | nullable: true, 146 | ), 147 | true, 148 | ), 149 | 150 | BridgeParameter( 151 | 'attribution', 152 | BridgeTypeAnnotation( 153 | BridgeTypeRef(CoreTypes.string, []), 154 | nullable: true, 155 | ), 156 | true, 157 | ), 158 | 159 | BridgeParameter( 160 | 'best', 161 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 162 | true, 163 | ), 164 | 165 | BridgeParameter( 166 | 'overlay', 167 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 168 | true, 169 | ), 170 | ], 171 | params: [], 172 | ), 173 | isFactory: false, 174 | ), 175 | }, 176 | 177 | methods: { 178 | 'initialize': BridgeMethodDef( 179 | BridgeFunctionDef( 180 | returns: BridgeTypeAnnotation( 181 | BridgeTypeRef(CoreTypes.future, [ 182 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 183 | ]), 184 | ), 185 | namedParams: [], 186 | params: [], 187 | ), 188 | ), 189 | 190 | 'buildLayer': BridgeMethodDef( 191 | BridgeFunctionDef( 192 | returns: BridgeTypeAnnotation( 193 | BridgeTypeRef( 194 | BridgeTypeSpec( 195 | 'package:flutter/src/widgets/framework.dart', 196 | 'Widget', 197 | ), 198 | [], 199 | ), 200 | ), 201 | namedParams: [ 202 | BridgeParameter( 203 | 'reset', 204 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 205 | true, 206 | ), 207 | ], 208 | params: [], 209 | ), 210 | ), 211 | }, 212 | getters: {}, 213 | setters: {}, 214 | fields: { 215 | 'id': BridgeFieldDef( 216 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 217 | isStatic: false, 218 | ), 219 | 220 | 'category': BridgeFieldDef( 221 | BridgeTypeAnnotation( 222 | BridgeTypeRef( 223 | BridgeTypeSpec( 224 | 'package:every_door/models/imagery.dart', 225 | 'ImageryCategory', 226 | ), 227 | [], 228 | ), 229 | nullable: true, 230 | ), 231 | isStatic: false, 232 | ), 233 | 234 | 'name': BridgeFieldDef( 235 | BridgeTypeAnnotation( 236 | BridgeTypeRef(CoreTypes.string, []), 237 | nullable: true, 238 | ), 239 | isStatic: false, 240 | ), 241 | 242 | 'icon': BridgeFieldDef( 243 | BridgeTypeAnnotation( 244 | BridgeTypeRef( 245 | BridgeTypeSpec( 246 | 'package:every_door/helpers/multi_icon.dart', 247 | 'MultiIcon', 248 | ), 249 | [], 250 | ), 251 | nullable: true, 252 | ), 253 | isStatic: false, 254 | ), 255 | 256 | 'attribution': BridgeFieldDef( 257 | BridgeTypeAnnotation( 258 | BridgeTypeRef(CoreTypes.string, []), 259 | nullable: true, 260 | ), 261 | isStatic: false, 262 | ), 263 | 264 | 'best': BridgeFieldDef( 265 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 266 | isStatic: false, 267 | ), 268 | 269 | 'overlay': BridgeFieldDef( 270 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 271 | isStatic: false, 272 | ), 273 | }, 274 | wrap: true, 275 | bridge: false, 276 | ); 277 | 278 | final $Instance _superclass; 279 | 280 | @override 281 | final Imagery $value; 282 | 283 | @override 284 | Imagery get $reified => $value; 285 | 286 | /// Wrap a [Imagery] in a [$Imagery] 287 | $Imagery.wrap(this.$value) : _superclass = $Object($value); 288 | 289 | @override 290 | int $getRuntimeType(Runtime runtime) => runtime.lookupType($spec); 291 | 292 | @override 293 | $Value? $getProperty(Runtime runtime, String identifier) { 294 | switch (identifier) { 295 | case 'id': 296 | final _id = $value.id; 297 | return $String(_id); 298 | 299 | case 'category': 300 | final _category = $value.category; 301 | return _category == null 302 | ? const $null() 303 | : $ImageryCategory.wrap(_category); 304 | 305 | case 'name': 306 | final _name = $value.name; 307 | return _name == null ? const $null() : $String(_name); 308 | 309 | case 'icon': 310 | final _icon = $value.icon; 311 | return _icon == null ? const $null() : $MultiIcon.wrap(_icon); 312 | 313 | case 'attribution': 314 | final _attribution = $value.attribution; 315 | return _attribution == null ? const $null() : $String(_attribution); 316 | 317 | case 'best': 318 | final _best = $value.best; 319 | return $bool(_best); 320 | 321 | case 'overlay': 322 | final _overlay = $value.overlay; 323 | return $bool(_overlay); 324 | case 'initialize': 325 | return __initialize; 326 | 327 | case 'buildLayer': 328 | return __buildLayer; 329 | } 330 | return _superclass.$getProperty(runtime, identifier); 331 | } 332 | 333 | static const $Function __initialize = $Function(_initialize); 334 | static $Value? _initialize( 335 | Runtime runtime, 336 | $Value? target, 337 | List<$Value?> args, 338 | ) { 339 | final self = target! as $Imagery; 340 | final result = self.$value.initialize(); 341 | return $Future.wrap(result.then((e) => null)); 342 | } 343 | 344 | static const $Function __buildLayer = $Function(_buildLayer); 345 | static $Value? _buildLayer( 346 | Runtime runtime, 347 | $Value? target, 348 | List<$Value?> args, 349 | ) { 350 | final self = target! as $Imagery; 351 | final result = self.$value.buildLayer(reset: args[0]?.$value ?? false); 352 | return $Widget.wrap(result); 353 | } 354 | 355 | @override 356 | void $setProperty(Runtime runtime, String identifier, $Value value) { 357 | return _superclass.$setProperty(runtime, identifier, value); 358 | } 359 | } 360 | -------------------------------------------------------------------------------- /lib/plugins/bindings/widgets/poi_marker.eval.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers 2 | import 'package:dart_eval/dart_eval_bridge.dart'; 3 | import 'package:every_door_plugin/widgets/poi_marker.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_eval/ui.dart'; 6 | import 'package:flutter_eval/widgets.dart'; 7 | import 'package:dart_eval/stdlib/core.dart'; 8 | 9 | /// dart_eval wrapper binding for [NumberedMarker] 10 | class $NumberedMarker implements $Instance { 11 | /// Configure this class for use in a [Runtime] 12 | static void configureForRuntime(Runtime runtime) { 13 | runtime.registerBridgeFunc( 14 | 'package:every_door/widgets/poi_marker.dart', 15 | 'NumberedMarker.', 16 | $NumberedMarker.$new, 17 | ); 18 | } 19 | 20 | /// Compile-time type specification of [$NumberedMarker] 21 | static const $spec = BridgeTypeSpec( 22 | 'package:every_door/widgets/poi_marker.dart', 23 | 'NumberedMarker', 24 | ); 25 | 26 | /// Compile-time type declaration of [$NumberedMarker] 27 | static const $type = BridgeTypeRef($spec); 28 | 29 | /// Compile-time class declaration of [$NumberedMarker] 30 | static const $declaration = BridgeClassDef( 31 | BridgeClassType( 32 | $type, 33 | 34 | $extends: BridgeTypeRef( 35 | BridgeTypeSpec( 36 | 'package:flutter/src/widgets/framework.dart', 37 | 'StatelessWidget', 38 | ), 39 | [], 40 | ), 41 | ), 42 | constructors: { 43 | '': BridgeConstructorDef( 44 | BridgeFunctionDef( 45 | returns: BridgeTypeAnnotation($type), 46 | namedParams: [ 47 | BridgeParameter( 48 | 'key', 49 | BridgeTypeAnnotation( 50 | BridgeTypeRef( 51 | BridgeTypeSpec( 52 | 'package:flutter/src/foundation/key.dart', 53 | 'Key', 54 | ), 55 | [], 56 | ), 57 | nullable: true, 58 | ), 59 | true, 60 | ), 61 | 62 | BridgeParameter( 63 | 'index', 64 | BridgeTypeAnnotation( 65 | BridgeTypeRef(CoreTypes.int, []), 66 | nullable: true, 67 | ), 68 | true, 69 | ), 70 | 71 | BridgeParameter( 72 | 'color', 73 | BridgeTypeAnnotation( 74 | BridgeTypeRef(BridgeTypeSpec('dart:ui', 'Color'), []), 75 | ), 76 | true, 77 | ), 78 | ], 79 | params: [], 80 | ), 81 | isFactory: false, 82 | ), 83 | }, 84 | 85 | methods: { 86 | 'build': BridgeMethodDef( 87 | BridgeFunctionDef( 88 | returns: BridgeTypeAnnotation( 89 | BridgeTypeRef( 90 | BridgeTypeSpec( 91 | 'package:flutter/src/widgets/framework.dart', 92 | 'Widget', 93 | ), 94 | [], 95 | ), 96 | ), 97 | namedParams: [], 98 | params: [ 99 | BridgeParameter( 100 | 'context', 101 | BridgeTypeAnnotation( 102 | BridgeTypeRef( 103 | BridgeTypeSpec( 104 | 'package:flutter/src/widgets/framework.dart', 105 | 'BuildContext', 106 | ), 107 | [], 108 | ), 109 | ), 110 | false, 111 | ), 112 | ], 113 | ), 114 | ), 115 | }, 116 | getters: {}, 117 | setters: {}, 118 | fields: { 119 | 'index': BridgeFieldDef( 120 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int, []), nullable: true), 121 | isStatic: false, 122 | ), 123 | 124 | 'color': BridgeFieldDef( 125 | BridgeTypeAnnotation( 126 | BridgeTypeRef(BridgeTypeSpec('dart:ui', 'Color'), []), 127 | ), 128 | isStatic: false, 129 | ), 130 | }, 131 | wrap: true, 132 | bridge: false, 133 | ); 134 | 135 | /// Wrapper for the [NumberedMarker.new] constructor 136 | static $Value? $new(Runtime runtime, $Value? thisValue, List<$Value?> args) { 137 | return $NumberedMarker.wrap( 138 | NumberedMarker( 139 | key: args[0]?.$value, 140 | index: args[1]?.$value, 141 | color: args[2]?.$value ?? Colors.white, 142 | ), 143 | ); 144 | } 145 | 146 | final $Instance _superclass; 147 | 148 | @override 149 | final NumberedMarker $value; 150 | 151 | @override 152 | NumberedMarker get $reified => $value; 153 | 154 | /// Wrap a [NumberedMarker] in a [$NumberedMarker] 155 | $NumberedMarker.wrap(this.$value) 156 | : _superclass = $StatelessWidget.wrap($value); 157 | 158 | @override 159 | int $getRuntimeType(Runtime runtime) => runtime.lookupType($spec); 160 | 161 | @override 162 | $Value? $getProperty(Runtime runtime, String identifier) { 163 | switch (identifier) { 164 | case 'index': 165 | final _index = $value.index; 166 | return _index == null ? const $null() : $int(_index); 167 | 168 | case 'color': 169 | final _color = $value.color; 170 | return $Color.wrap(_color); 171 | case 'build': 172 | return __build; 173 | } 174 | return _superclass.$getProperty(runtime, identifier); 175 | } 176 | 177 | static const $Function __build = $Function(_build); 178 | static $Value? _build(Runtime runtime, $Value? target, List<$Value?> args) { 179 | final self = target! as $NumberedMarker; 180 | final result = self.$value.build(args[0]!.$value); 181 | return $Widget.wrap(result); 182 | } 183 | 184 | @override 185 | void $setProperty(Runtime runtime, String identifier, $Value value) { 186 | return _superclass.$setProperty(runtime, identifier, value); 187 | } 188 | } 189 | 190 | /// dart_eval wrapper binding for [ColoredMarker] 191 | class $ColoredMarker implements $Instance { 192 | /// Configure this class for use in a [Runtime] 193 | static void configureForRuntime(Runtime runtime) { 194 | runtime.registerBridgeFunc( 195 | 'package:every_door/widgets/poi_marker.dart', 196 | 'ColoredMarker.', 197 | $ColoredMarker.$new, 198 | ); 199 | } 200 | 201 | /// Compile-time type specification of [$ColoredMarker] 202 | static const $spec = BridgeTypeSpec( 203 | 'package:every_door/widgets/poi_marker.dart', 204 | 'ColoredMarker', 205 | ); 206 | 207 | /// Compile-time type declaration of [$ColoredMarker] 208 | static const $type = BridgeTypeRef($spec); 209 | 210 | /// Compile-time class declaration of [$ColoredMarker] 211 | static const $declaration = BridgeClassDef( 212 | BridgeClassType( 213 | $type, 214 | 215 | $extends: BridgeTypeRef( 216 | BridgeTypeSpec( 217 | 'package:flutter/src/widgets/framework.dart', 218 | 'StatelessWidget', 219 | ), 220 | [], 221 | ), 222 | ), 223 | constructors: { 224 | '': BridgeConstructorDef( 225 | BridgeFunctionDef( 226 | returns: BridgeTypeAnnotation($type), 227 | namedParams: [ 228 | BridgeParameter( 229 | 'key', 230 | BridgeTypeAnnotation( 231 | BridgeTypeRef( 232 | BridgeTypeSpec( 233 | 'package:flutter/src/foundation/key.dart', 234 | 'Key', 235 | ), 236 | [], 237 | ), 238 | nullable: true, 239 | ), 240 | true, 241 | ), 242 | 243 | BridgeParameter( 244 | 'color', 245 | BridgeTypeAnnotation( 246 | BridgeTypeRef(BridgeTypeSpec('dart:ui', 'Color'), []), 247 | ), 248 | true, 249 | ), 250 | 251 | BridgeParameter( 252 | 'isIncomplete', 253 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 254 | true, 255 | ), 256 | ], 257 | params: [], 258 | ), 259 | isFactory: false, 260 | ), 261 | }, 262 | 263 | methods: { 264 | 'build': BridgeMethodDef( 265 | BridgeFunctionDef( 266 | returns: BridgeTypeAnnotation( 267 | BridgeTypeRef( 268 | BridgeTypeSpec( 269 | 'package:flutter/src/widgets/framework.dart', 270 | 'Widget', 271 | ), 272 | [], 273 | ), 274 | ), 275 | namedParams: [], 276 | params: [ 277 | BridgeParameter( 278 | 'context', 279 | BridgeTypeAnnotation( 280 | BridgeTypeRef( 281 | BridgeTypeSpec( 282 | 'package:flutter/src/widgets/framework.dart', 283 | 'BuildContext', 284 | ), 285 | [], 286 | ), 287 | ), 288 | false, 289 | ), 290 | ], 291 | ), 292 | ), 293 | }, 294 | getters: {}, 295 | setters: {}, 296 | fields: { 297 | 'color': BridgeFieldDef( 298 | BridgeTypeAnnotation( 299 | BridgeTypeRef(BridgeTypeSpec('dart:ui', 'Color'), []), 300 | ), 301 | isStatic: false, 302 | ), 303 | 304 | 'isIncomplete': BridgeFieldDef( 305 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 306 | isStatic: false, 307 | ), 308 | }, 309 | wrap: true, 310 | bridge: false, 311 | ); 312 | 313 | /// Wrapper for the [ColoredMarker.new] constructor 314 | static $Value? $new(Runtime runtime, $Value? thisValue, List<$Value?> args) { 315 | return $ColoredMarker.wrap( 316 | ColoredMarker( 317 | key: args[0]?.$value, 318 | color: args[1]?.$value ?? Colors.black, 319 | isIncomplete: args[2]?.$value ?? false, 320 | ), 321 | ); 322 | } 323 | 324 | final $Instance _superclass; 325 | 326 | @override 327 | final ColoredMarker $value; 328 | 329 | @override 330 | ColoredMarker get $reified => $value; 331 | 332 | /// Wrap a [ColoredMarker] in a [$ColoredMarker] 333 | $ColoredMarker.wrap(this.$value) 334 | : _superclass = $StatelessWidget.wrap($value); 335 | 336 | @override 337 | int $getRuntimeType(Runtime runtime) => runtime.lookupType($spec); 338 | 339 | @override 340 | $Value? $getProperty(Runtime runtime, String identifier) { 341 | switch (identifier) { 342 | case 'color': 343 | final _color = $value.color; 344 | return $Color.wrap(_color); 345 | 346 | case 'isIncomplete': 347 | final _isIncomplete = $value.isIncomplete; 348 | return $bool(_isIncomplete); 349 | case 'build': 350 | return __build; 351 | } 352 | return _superclass.$getProperty(runtime, identifier); 353 | } 354 | 355 | static const $Function __build = $Function(_build); 356 | static $Value? _build(Runtime runtime, $Value? target, List<$Value?> args) { 357 | final self = target! as $ColoredMarker; 358 | final result = self.$value.build(args[0]!.$value); 359 | return $Widget.wrap(result); 360 | } 361 | 362 | @override 363 | void $setProperty(Runtime runtime, String identifier, $Value value) { 364 | return _superclass.$setProperty(runtime, identifier, value); 365 | } 366 | } 367 | -------------------------------------------------------------------------------- /lib/plugins/bindings/plugins/ext_overlay.eval.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers 2 | import 'package:dart_eval/dart_eval_bridge.dart'; 3 | import 'package:every_door_plugin/plugins/ext_overlay.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_map/flutter_map.dart'; 6 | import 'package:flutter_eval/widgets.dart'; 7 | import 'package:flutter_map_eval/flutter_map/flutter_map_eval.dart'; 8 | import 'package:every_door_plugin/plugins/bindings/models/imagery.eval.dart'; 9 | import 'package:dart_eval/stdlib/core.dart'; 10 | 11 | /// dart_eval wrapper binding for [ExtOverlay] 12 | class $ExtOverlay implements $Instance { 13 | /// Configure this class for use in a [Runtime] 14 | static void configureForRuntime(Runtime runtime) { 15 | runtime.registerBridgeFunc( 16 | 'package:every_door/plugins/ext_overlay.dart', 17 | 'ExtOverlay.', 18 | $ExtOverlay.$new, 19 | ); 20 | } 21 | 22 | /// Compile-time type specification of [$ExtOverlay] 23 | static const $spec = BridgeTypeSpec( 24 | 'package:every_door/plugins/ext_overlay.dart', 25 | 'ExtOverlay', 26 | ); 27 | 28 | /// Compile-time type declaration of [$ExtOverlay] 29 | static const $type = BridgeTypeRef($spec); 30 | 31 | /// Compile-time class declaration of [$ExtOverlay] 32 | static const $declaration = BridgeClassDef( 33 | BridgeClassType( 34 | $type, 35 | 36 | $extends: BridgeTypeRef( 37 | BridgeTypeSpec('package:every_door/models/imagery.dart', 'Imagery'), 38 | [], 39 | ), 40 | ), 41 | constructors: { 42 | '': BridgeConstructorDef( 43 | BridgeFunctionDef( 44 | returns: BridgeTypeAnnotation($type), 45 | namedParams: [ 46 | BridgeParameter( 47 | 'id', 48 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 49 | false, 50 | ), 51 | 52 | BridgeParameter( 53 | 'attribution', 54 | BridgeTypeAnnotation( 55 | BridgeTypeRef(CoreTypes.string, []), 56 | nullable: true, 57 | ), 58 | true, 59 | ), 60 | 61 | BridgeParameter( 62 | 'updateInMeters', 63 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int, [])), 64 | true, 65 | ), 66 | 67 | BridgeParameter( 68 | 'build', 69 | BridgeTypeAnnotation( 70 | BridgeTypeRef.genericFunction( 71 | BridgeFunctionDef( 72 | returns: BridgeTypeAnnotation( 73 | BridgeTypeRef( 74 | BridgeTypeSpec( 75 | 'package:flutter/src/widgets/framework.dart', 76 | 'Widget', 77 | ), 78 | [], 79 | ), 80 | ), 81 | params: [ 82 | BridgeParameter( 83 | 'context', 84 | BridgeTypeAnnotation( 85 | BridgeTypeRef( 86 | BridgeTypeSpec( 87 | 'package:flutter/src/widgets/framework.dart', 88 | 'BuildContext', 89 | ), 90 | [], 91 | ), 92 | ), 93 | false, 94 | ), 95 | 96 | BridgeParameter( 97 | 'data', 98 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.dynamic)), 99 | false, 100 | ), 101 | ], 102 | namedParams: [], 103 | ), 104 | ), 105 | ), 106 | false, 107 | ), 108 | 109 | BridgeParameter( 110 | 'update', 111 | BridgeTypeAnnotation( 112 | BridgeTypeRef.genericFunction( 113 | BridgeFunctionDef( 114 | returns: BridgeTypeAnnotation( 115 | BridgeTypeRef(CoreTypes.future, [ 116 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.dynamic)), 117 | ]), 118 | ), 119 | params: [ 120 | BridgeParameter( 121 | '', 122 | BridgeTypeAnnotation( 123 | BridgeTypeRef( 124 | BridgeTypeSpec( 125 | 'package:flutter_map/src/geo/latlng_bounds.dart', 126 | 'LatLngBounds', 127 | ), 128 | [], 129 | ), 130 | ), 131 | false, 132 | ), 133 | ], 134 | namedParams: [], 135 | ), 136 | ), 137 | nullable: true, 138 | ), 139 | true, 140 | ), 141 | ], 142 | params: [], 143 | ), 144 | isFactory: false, 145 | ), 146 | }, 147 | 148 | methods: { 149 | 'buildLayer': BridgeMethodDef( 150 | BridgeFunctionDef( 151 | returns: BridgeTypeAnnotation( 152 | BridgeTypeRef( 153 | BridgeTypeSpec( 154 | 'package:flutter/src/widgets/framework.dart', 155 | 'Widget', 156 | ), 157 | [], 158 | ), 159 | ), 160 | namedParams: [ 161 | BridgeParameter( 162 | 'reset', 163 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 164 | true, 165 | ), 166 | ], 167 | params: [], 168 | ), 169 | ), 170 | }, 171 | getters: {}, 172 | setters: {}, 173 | fields: { 174 | 'build': BridgeFieldDef( 175 | BridgeTypeAnnotation( 176 | BridgeTypeRef.genericFunction( 177 | BridgeFunctionDef( 178 | returns: BridgeTypeAnnotation( 179 | BridgeTypeRef( 180 | BridgeTypeSpec( 181 | 'package:flutter/src/widgets/framework.dart', 182 | 'Widget', 183 | ), 184 | [], 185 | ), 186 | ), 187 | params: [ 188 | BridgeParameter( 189 | 'context', 190 | BridgeTypeAnnotation( 191 | BridgeTypeRef( 192 | BridgeTypeSpec( 193 | 'package:flutter/src/widgets/framework.dart', 194 | 'BuildContext', 195 | ), 196 | [], 197 | ), 198 | ), 199 | false, 200 | ), 201 | 202 | BridgeParameter( 203 | 'data', 204 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.dynamic)), 205 | false, 206 | ), 207 | ], 208 | namedParams: [], 209 | ), 210 | ), 211 | ), 212 | isStatic: false, 213 | ), 214 | 215 | 'updateInMeters': BridgeFieldDef( 216 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int, [])), 217 | isStatic: false, 218 | ), 219 | 220 | 'update': BridgeFieldDef( 221 | BridgeTypeAnnotation( 222 | BridgeTypeRef.genericFunction( 223 | BridgeFunctionDef( 224 | returns: BridgeTypeAnnotation( 225 | BridgeTypeRef(CoreTypes.future, [ 226 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.dynamic)), 227 | ]), 228 | ), 229 | params: [ 230 | BridgeParameter( 231 | '', 232 | BridgeTypeAnnotation( 233 | BridgeTypeRef( 234 | BridgeTypeSpec( 235 | 'package:flutter_map/src/geo/latlng_bounds.dart', 236 | 'LatLngBounds', 237 | ), 238 | [], 239 | ), 240 | ), 241 | false, 242 | ), 243 | ], 244 | namedParams: [], 245 | ), 246 | ), 247 | nullable: true, 248 | ), 249 | isStatic: false, 250 | ), 251 | }, 252 | wrap: true, 253 | bridge: false, 254 | ); 255 | 256 | /// Wrapper for the [ExtOverlay.new] constructor 257 | static $Value? $new(Runtime runtime, $Value? thisValue, List<$Value?> args) { 258 | return $ExtOverlay.wrap( 259 | ExtOverlay( 260 | id: args[0]!.$value, 261 | attribution: args[1]?.$value, 262 | updateInMeters: args[2]?.$value ?? 0, 263 | build: (BuildContext context, dynamic data) { 264 | return (args[3]! as EvalCallable)(runtime, null, [ 265 | $BuildContext.wrap(context), 266 | $Object(data), 267 | ])?.$value; 268 | }, 269 | update: (LatLngBounds arg0) { 270 | return (args[4]! as EvalCallable?)?.call(runtime, null, [ 271 | $LatLngBounds.wrap(arg0), 272 | ])?.$value; 273 | }, 274 | ), 275 | ); 276 | } 277 | 278 | final $Instance _superclass; 279 | 280 | @override 281 | final ExtOverlay $value; 282 | 283 | @override 284 | ExtOverlay get $reified => $value; 285 | 286 | /// Wrap a [ExtOverlay] in a [$ExtOverlay] 287 | $ExtOverlay.wrap(this.$value) : _superclass = $Imagery.wrap($value); 288 | 289 | @override 290 | int $getRuntimeType(Runtime runtime) => runtime.lookupType($spec); 291 | 292 | @override 293 | $Value? $getProperty(Runtime runtime, String identifier) { 294 | switch (identifier) { 295 | case 'build': 296 | final _build = $value.build; 297 | return $Function((runtime, target, args) { 298 | final funcResult = _build(args[0]!.$value, args[1]!.$value); 299 | return $Widget.wrap(funcResult); 300 | }); 301 | 302 | case 'updateInMeters': 303 | final _updateInMeters = $value.updateInMeters; 304 | return $int(_updateInMeters); 305 | 306 | case 'update': 307 | final _update = $value.update; 308 | return _update == null 309 | ? const $null() 310 | : $Function((runtime, target, args) { 311 | final funcResult = _update(args[0]!.$value); 312 | return $Future.wrap(funcResult.then((e) => $Object(e))); 313 | }); 314 | case 'buildLayer': 315 | return __buildLayer; 316 | } 317 | return _superclass.$getProperty(runtime, identifier); 318 | } 319 | 320 | static const $Function __buildLayer = $Function(_buildLayer); 321 | static $Value? _buildLayer( 322 | Runtime runtime, 323 | $Value? target, 324 | List<$Value?> args, 325 | ) { 326 | final self = target! as $ExtOverlay; 327 | final result = self.$value.buildLayer(reset: args[0]?.$value ?? false); 328 | return $Widget.wrap(result); 329 | } 330 | 331 | @override 332 | void $setProperty(Runtime runtime, String identifier, $Value value) { 333 | return _superclass.$setProperty(runtime, identifier, value); 334 | } 335 | } 336 | -------------------------------------------------------------------------------- /lib/plugins/bindings/plugins/preferences.eval.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers 2 | import 'package:dart_eval/dart_eval_bridge.dart'; 3 | import 'package:every_door_plugin/plugins/preferences.dart'; 4 | import 'package:dart_eval/stdlib/core.dart'; 5 | 6 | /// dart_eval wrapper binding for [PluginPreferences] 7 | class $PluginPreferences implements $Instance { 8 | /// Configure this class for use in a [Runtime] 9 | static void configureForRuntime(Runtime runtime) {} 10 | 11 | /// Compile-time type specification of [$PluginPreferences] 12 | static const $spec = BridgeTypeSpec( 13 | 'package:every_door/plugins/preferences.dart', 14 | 'PluginPreferences', 15 | ); 16 | 17 | /// Compile-time type declaration of [$PluginPreferences] 18 | static const $type = BridgeTypeRef($spec); 19 | 20 | /// Compile-time class declaration of [$PluginPreferences] 21 | static const $declaration = BridgeClassDef( 22 | BridgeClassType($type), 23 | constructors: {}, 24 | methods: { 25 | 'setString': BridgeMethodDef( 26 | BridgeFunctionDef( 27 | returns: BridgeTypeAnnotation( 28 | BridgeTypeRef(CoreTypes.future, [ 29 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 30 | ]), 31 | ), 32 | namedParams: [], 33 | params: [ 34 | BridgeParameter( 35 | 'name', 36 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 37 | false, 38 | ), 39 | BridgeParameter( 40 | 'value', 41 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 42 | false, 43 | ), 44 | ], 45 | ), 46 | ), 47 | 'setInt': BridgeMethodDef( 48 | BridgeFunctionDef( 49 | returns: BridgeTypeAnnotation( 50 | BridgeTypeRef(CoreTypes.future, [ 51 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 52 | ]), 53 | ), 54 | namedParams: [], 55 | params: [ 56 | BridgeParameter( 57 | 'name', 58 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 59 | false, 60 | ), 61 | BridgeParameter( 62 | 'value', 63 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int, [])), 64 | false, 65 | ), 66 | ], 67 | ), 68 | ), 69 | 'setBool': BridgeMethodDef( 70 | BridgeFunctionDef( 71 | returns: BridgeTypeAnnotation( 72 | BridgeTypeRef(CoreTypes.future, [ 73 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 74 | ]), 75 | ), 76 | namedParams: [], 77 | params: [ 78 | BridgeParameter( 79 | 'name', 80 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 81 | false, 82 | ), 83 | BridgeParameter( 84 | 'value', 85 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool, [])), 86 | false, 87 | ), 88 | ], 89 | ), 90 | ), 91 | 'setDouble': BridgeMethodDef( 92 | BridgeFunctionDef( 93 | returns: BridgeTypeAnnotation( 94 | BridgeTypeRef(CoreTypes.future, [ 95 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 96 | ]), 97 | ), 98 | namedParams: [], 99 | params: [ 100 | BridgeParameter( 101 | 'name', 102 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 103 | false, 104 | ), 105 | BridgeParameter( 106 | 'value', 107 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.double, [])), 108 | false, 109 | ), 110 | ], 111 | ), 112 | ), 113 | 'setStringList': BridgeMethodDef( 114 | BridgeFunctionDef( 115 | returns: BridgeTypeAnnotation( 116 | BridgeTypeRef(CoreTypes.future, [ 117 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 118 | ]), 119 | ), 120 | namedParams: [], 121 | params: [ 122 | BridgeParameter( 123 | 'name', 124 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 125 | false, 126 | ), 127 | BridgeParameter( 128 | 'value', 129 | BridgeTypeAnnotation( 130 | BridgeTypeRef(CoreTypes.list, [ 131 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 132 | ]), 133 | ), 134 | false, 135 | ), 136 | ], 137 | ), 138 | ), 139 | 'getString': BridgeMethodDef( 140 | BridgeFunctionDef( 141 | returns: BridgeTypeAnnotation( 142 | BridgeTypeRef(CoreTypes.string, []), 143 | nullable: true, 144 | ), 145 | namedParams: [], 146 | params: [ 147 | BridgeParameter( 148 | 'name', 149 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 150 | false, 151 | ), 152 | ], 153 | ), 154 | ), 155 | 'getInt': BridgeMethodDef( 156 | BridgeFunctionDef( 157 | returns: BridgeTypeAnnotation( 158 | BridgeTypeRef(CoreTypes.int, []), 159 | nullable: true, 160 | ), 161 | namedParams: [], 162 | params: [ 163 | BridgeParameter( 164 | 'name', 165 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 166 | false, 167 | ), 168 | ], 169 | ), 170 | ), 171 | 'getBool': BridgeMethodDef( 172 | BridgeFunctionDef( 173 | returns: BridgeTypeAnnotation( 174 | BridgeTypeRef(CoreTypes.bool, []), 175 | nullable: true, 176 | ), 177 | namedParams: [], 178 | params: [ 179 | BridgeParameter( 180 | 'name', 181 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 182 | false, 183 | ), 184 | ], 185 | ), 186 | ), 187 | 'getDouble': BridgeMethodDef( 188 | BridgeFunctionDef( 189 | returns: BridgeTypeAnnotation( 190 | BridgeTypeRef(CoreTypes.double, []), 191 | nullable: true, 192 | ), 193 | namedParams: [], 194 | params: [ 195 | BridgeParameter( 196 | 'name', 197 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 198 | false, 199 | ), 200 | ], 201 | ), 202 | ), 203 | 'getStringList': BridgeMethodDef( 204 | BridgeFunctionDef( 205 | returns: BridgeTypeAnnotation( 206 | BridgeTypeRef(CoreTypes.list, [ 207 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 208 | ]), 209 | nullable: true, 210 | ), 211 | namedParams: [], 212 | params: [ 213 | BridgeParameter( 214 | 'name', 215 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 216 | false, 217 | ), 218 | ], 219 | ), 220 | ), 221 | }, 222 | getters: {}, 223 | setters: {}, 224 | fields: {}, 225 | wrap: true, 226 | bridge: false, 227 | ); 228 | 229 | final $Instance _superclass; 230 | 231 | @override 232 | final PluginPreferences $value; 233 | 234 | @override 235 | PluginPreferences get $reified => $value; 236 | 237 | /// Wrap a [PluginPreferences] in a [$PluginPreferences] 238 | $PluginPreferences.wrap(this.$value) : _superclass = $Object($value); 239 | 240 | @override 241 | int $getRuntimeType(Runtime runtime) => runtime.lookupType($spec); 242 | 243 | @override 244 | $Value? $getProperty(Runtime runtime, String identifier) { 245 | switch (identifier) { 246 | case 'setString': 247 | return __setString; 248 | 249 | case 'setInt': 250 | return __setInt; 251 | 252 | case 'setBool': 253 | return __setBool; 254 | 255 | case 'setDouble': 256 | return __setDouble; 257 | 258 | case 'setStringList': 259 | return __setStringList; 260 | 261 | case 'getString': 262 | return __getString; 263 | 264 | case 'getInt': 265 | return __getInt; 266 | 267 | case 'getBool': 268 | return __getBool; 269 | 270 | case 'getDouble': 271 | return __getDouble; 272 | 273 | case 'getStringList': 274 | return __getStringList; 275 | } 276 | return _superclass.$getProperty(runtime, identifier); 277 | } 278 | 279 | static const $Function __setString = $Function(_setString); 280 | static $Value? _setString( 281 | Runtime runtime, 282 | $Value? target, 283 | List<$Value?> args, 284 | ) { 285 | final self = target! as $PluginPreferences; 286 | final result = self.$value.setString(args[0]!.$value, args[1]!.$value); 287 | return $Future.wrap(result.then((e) => null)); 288 | } 289 | 290 | static const $Function __setInt = $Function(_setInt); 291 | static $Value? _setInt(Runtime runtime, $Value? target, List<$Value?> args) { 292 | final self = target! as $PluginPreferences; 293 | final result = self.$value.setInt(args[0]!.$value, args[1]!.$value); 294 | return $Future.wrap(result.then((e) => null)); 295 | } 296 | 297 | static const $Function __setBool = $Function(_setBool); 298 | static $Value? _setBool(Runtime runtime, $Value? target, List<$Value?> args) { 299 | final self = target! as $PluginPreferences; 300 | final result = self.$value.setBool(args[0]!.$value, args[1]!.$value); 301 | return $Future.wrap(result.then((e) => null)); 302 | } 303 | 304 | static const $Function __setDouble = $Function(_setDouble); 305 | static $Value? _setDouble( 306 | Runtime runtime, 307 | $Value? target, 308 | List<$Value?> args, 309 | ) { 310 | final self = target! as $PluginPreferences; 311 | final result = self.$value.setDouble(args[0]!.$value, args[1]!.$value); 312 | return $Future.wrap(result.then((e) => null)); 313 | } 314 | 315 | static const $Function __setStringList = $Function(_setStringList); 316 | static $Value? _setStringList( 317 | Runtime runtime, 318 | $Value? target, 319 | List<$Value?> args, 320 | ) { 321 | final self = target! as $PluginPreferences; 322 | final result = self.$value.setStringList( 323 | args[0]!.$value, 324 | (args[1]!.$reified as List).cast(), 325 | ); 326 | return $Future.wrap(result.then((e) => null)); 327 | } 328 | 329 | static const $Function __getString = $Function(_getString); 330 | static $Value? _getString( 331 | Runtime runtime, 332 | $Value? target, 333 | List<$Value?> args, 334 | ) { 335 | final self = target! as $PluginPreferences; 336 | final result = self.$value.getString(args[0]!.$value); 337 | return result == null ? const $null() : $String(result); 338 | } 339 | 340 | static const $Function __getInt = $Function(_getInt); 341 | static $Value? _getInt(Runtime runtime, $Value? target, List<$Value?> args) { 342 | final self = target! as $PluginPreferences; 343 | final result = self.$value.getInt(args[0]!.$value); 344 | return result == null ? const $null() : $int(result); 345 | } 346 | 347 | static const $Function __getBool = $Function(_getBool); 348 | static $Value? _getBool(Runtime runtime, $Value? target, List<$Value?> args) { 349 | final self = target! as $PluginPreferences; 350 | final result = self.$value.getBool(args[0]!.$value); 351 | return result == null ? const $null() : $bool(result); 352 | } 353 | 354 | static const $Function __getDouble = $Function(_getDouble); 355 | static $Value? _getDouble( 356 | Runtime runtime, 357 | $Value? target, 358 | List<$Value?> args, 359 | ) { 360 | final self = target! as $PluginPreferences; 361 | final result = self.$value.getDouble(args[0]!.$value); 362 | return result == null ? const $null() : $double(result); 363 | } 364 | 365 | static const $Function __getStringList = $Function(_getStringList); 366 | static $Value? _getStringList( 367 | Runtime runtime, 368 | $Value? target, 369 | List<$Value?> args, 370 | ) { 371 | final self = target! as $PluginPreferences; 372 | final result = self.$value.getStringList(args[0]!.$value); 373 | return result == null 374 | ? const $null() 375 | : $List.view(result, (e) => $String(e)); 376 | } 377 | 378 | @override 379 | void $setProperty(Runtime runtime, String identifier, $Value value) { 380 | return _superclass.$setProperty(runtime, identifier, value); 381 | } 382 | } 383 | -------------------------------------------------------------------------------- /lib/plugins/bindings/plugins/interface.eval.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers 2 | import 'package:dart_eval/dart_eval_bridge.dart'; 3 | import 'package:dart_eval/stdlib/core.dart'; 4 | import 'package:every_door_plugin/plugins/bindings/helpers/auth/controller.eval.dart'; 5 | import 'package:every_door_plugin/plugins/bindings/models/plugin.eval.dart'; 6 | import 'package:every_door_plugin/plugins/bindings/plugins/events.eval.dart'; 7 | import 'package:every_door_plugin/plugins/bindings/plugins/preferences.eval.dart'; 8 | import 'package:every_door_plugin/plugins/bindings/plugins/providers.eval.dart'; 9 | import 'package:every_door_plugin/plugins/bindings/screens/modes/definitions/base.eval.dart'; 10 | import 'package:every_door_plugin/screens/modes/definitions/base.dart'; 11 | import 'package:every_door_plugin/plugins/interface.dart'; 12 | import 'package:flutter_map_eval/logging/logging_eval.dart'; 13 | 14 | /// dart_eval wrapper binding for [EveryDoorApp] 15 | class $EveryDoorApp implements $Instance { 16 | /// Configure this class for use in a [Runtime] 17 | static void configureForRuntime(Runtime runtime) {} 18 | 19 | /// Compile-time type specification of [$EveryDoorApp] 20 | static const $spec = BridgeTypeSpec( 21 | 'package:every_door/plugins/interface.dart', 22 | 'EveryDoorApp', 23 | ); 24 | 25 | /// Compile-time type declaration of [$EveryDoorApp] 26 | static const $type = BridgeTypeRef($spec); 27 | 28 | /// Compile-time class declaration of [$EveryDoorApp] 29 | static const $declaration = BridgeClassDef( 30 | BridgeClassType($type), 31 | constructors: {}, 32 | methods: { 33 | 'repaint': BridgeMethodDef( 34 | BridgeFunctionDef( 35 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 36 | namedParams: [], 37 | params: [], 38 | ), 39 | ), 40 | 'addOverlay': BridgeMethodDef( 41 | BridgeFunctionDef( 42 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 43 | namedParams: [], 44 | params: [ 45 | BridgeParameter( 46 | 'imagery', 47 | BridgeTypeAnnotation( 48 | BridgeTypeRef( 49 | BridgeTypeSpec( 50 | 'package:every_door/models/imagery.dart', 51 | 'Imagery', 52 | ), 53 | [], 54 | ), 55 | ), 56 | false, 57 | ), 58 | ], 59 | ), 60 | ), 61 | 'addMode': BridgeMethodDef( 62 | BridgeFunctionDef( 63 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 64 | namedParams: [], 65 | params: [ 66 | BridgeParameter( 67 | 'mode', 68 | BridgeTypeAnnotation( 69 | BridgeTypeRef( 70 | BridgeTypeSpec( 71 | 'package:every_door/screens/modes/definitions/base.dart', 72 | 'BaseModeDefinition', 73 | ), 74 | [], 75 | ), 76 | ), 77 | false, 78 | ), 79 | ], 80 | ), 81 | ), 82 | 'removeMode': BridgeMethodDef( 83 | BridgeFunctionDef( 84 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 85 | namedParams: [], 86 | params: [ 87 | BridgeParameter( 88 | 'name', 89 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 90 | false, 91 | ), 92 | ], 93 | ), 94 | ), 95 | 'eachMode': BridgeMethodDef( 96 | BridgeFunctionDef( 97 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 98 | namedParams: [], 99 | params: [ 100 | BridgeParameter( 101 | 'callback', 102 | BridgeTypeAnnotation( 103 | BridgeTypeRef.genericFunction( 104 | BridgeFunctionDef( 105 | returns: BridgeTypeAnnotation( 106 | BridgeTypeRef(CoreTypes.dynamic), 107 | ), 108 | params: [ 109 | BridgeParameter( 110 | '', 111 | BridgeTypeAnnotation( 112 | BridgeTypeRef( 113 | BridgeTypeSpec( 114 | 'package:every_door/screens/modes/definitions/base.dart', 115 | 'BaseModeDefinition', 116 | ), 117 | [], 118 | ), 119 | ), 120 | false, 121 | ), 122 | ], 123 | namedParams: [], 124 | ), 125 | ), 126 | ), 127 | false, 128 | ), 129 | ], 130 | ), 131 | ), 132 | 'addAuthProvider': BridgeMethodDef( 133 | BridgeFunctionDef( 134 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)), 135 | namedParams: [], 136 | params: [ 137 | BridgeParameter( 138 | 'name', 139 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 140 | false, 141 | ), 142 | BridgeParameter( 143 | 'provider', 144 | BridgeTypeAnnotation( 145 | BridgeTypeRef( 146 | BridgeTypeSpec( 147 | 'package:every_door/helpers/auth/provider.dart', 148 | 'AuthProvider', 149 | ), 150 | [], 151 | ), 152 | ), 153 | false, 154 | ), 155 | ], 156 | ), 157 | ), 158 | 'auth': BridgeMethodDef( 159 | BridgeFunctionDef( 160 | returns: BridgeTypeAnnotation( 161 | BridgeTypeRef( 162 | BridgeTypeSpec( 163 | 'package:every_door/helpers/auth/controller.dart', 164 | 'AuthController', 165 | ), 166 | [], 167 | ), 168 | ), 169 | namedParams: [], 170 | params: [ 171 | BridgeParameter( 172 | 'name', 173 | BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string, [])), 174 | false, 175 | ), 176 | ], 177 | ), 178 | ), 179 | }, 180 | getters: {}, 181 | setters: {}, 182 | fields: { 183 | 'plugin': BridgeFieldDef( 184 | BridgeTypeAnnotation( 185 | BridgeTypeRef( 186 | BridgeTypeSpec('package:every_door/models/plugin.dart', 'Plugin'), 187 | [], 188 | ), 189 | ), 190 | isStatic: false, 191 | ), 192 | 'onRepaint': BridgeFieldDef( 193 | BridgeTypeAnnotation( 194 | BridgeTypeRef.genericFunction( 195 | BridgeFunctionDef( 196 | returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.dynamic)), 197 | params: [], 198 | namedParams: [], 199 | ), 200 | ), 201 | nullable: true, 202 | ), 203 | isStatic: false, 204 | ), 205 | 'preferences': BridgeFieldDef( 206 | BridgeTypeAnnotation( 207 | BridgeTypeRef( 208 | BridgeTypeSpec( 209 | 'package:every_door/plugins/preferences.dart', 210 | 'PluginPreferences', 211 | ), 212 | [], 213 | ), 214 | ), 215 | isStatic: false, 216 | ), 217 | 'providers': BridgeFieldDef( 218 | BridgeTypeAnnotation( 219 | BridgeTypeRef( 220 | BridgeTypeSpec( 221 | 'package:every_door/plugins/providers.dart', 222 | 'PluginProviders', 223 | ), 224 | [], 225 | ), 226 | ), 227 | isStatic: false, 228 | ), 229 | 'events': BridgeFieldDef( 230 | BridgeTypeAnnotation( 231 | BridgeTypeRef( 232 | BridgeTypeSpec( 233 | 'package:every_door/plugins/events.dart', 234 | 'PluginEvents', 235 | ), 236 | [], 237 | ), 238 | ), 239 | isStatic: false, 240 | ), 241 | 'logger': BridgeFieldDef( 242 | BridgeTypeAnnotation( 243 | BridgeTypeRef( 244 | BridgeTypeSpec('package:logging/src/logger.dart', 'Logger'), 245 | [], 246 | ), 247 | ), 248 | isStatic: false, 249 | ), 250 | }, 251 | wrap: true, 252 | bridge: false, 253 | ); 254 | 255 | final $Instance _superclass; 256 | 257 | @override 258 | final EveryDoorApp $value; 259 | 260 | @override 261 | EveryDoorApp get $reified => $value; 262 | 263 | /// Wrap a [EveryDoorApp] in a [$EveryDoorApp] 264 | $EveryDoorApp.wrap(this.$value) : _superclass = $Object($value); 265 | 266 | @override 267 | int $getRuntimeType(Runtime runtime) => runtime.lookupType($spec); 268 | 269 | @override 270 | $Value? $getProperty(Runtime runtime, String identifier) { 271 | switch (identifier) { 272 | case 'plugin': 273 | final _plugin = $value.plugin; 274 | return $Plugin.wrap(_plugin); 275 | 276 | case 'onRepaint': 277 | final _onRepaint = $value.onRepaint; 278 | return _onRepaint == null 279 | ? const $null() 280 | : $Function((runtime, target, args) { 281 | final funcResult = _onRepaint(); 282 | return $Object(funcResult); 283 | }); 284 | 285 | case 'preferences': 286 | final _preferences = $value.preferences; 287 | return $PluginPreferences.wrap(_preferences); 288 | 289 | case 'providers': 290 | final _providers = $value.providers; 291 | return $PluginProviders.wrap(_providers); 292 | 293 | case 'events': 294 | final _events = $value.events; 295 | return $PluginEvents.wrap(_events); 296 | 297 | case 'logger': 298 | final _logger = $value.logger; 299 | return $Logger.wrap(_logger); 300 | 301 | case 'repaint': 302 | return __repaint; 303 | 304 | case 'addOverlay': 305 | return __addOverlay; 306 | 307 | case 'addMode': 308 | return __addMode; 309 | 310 | case 'removeMode': 311 | return __removeMode; 312 | 313 | case 'eachMode': 314 | return __eachMode; 315 | 316 | case 'addAuthProvider': 317 | return __addAuthProvider; 318 | 319 | case 'auth': 320 | return __auth; 321 | } 322 | return _superclass.$getProperty(runtime, identifier); 323 | } 324 | 325 | static const $Function __repaint = $Function(_repaint); 326 | static $Value? _repaint(Runtime runtime, $Value? target, List<$Value?> args) { 327 | final self = target! as $EveryDoorApp; 328 | self.$value.repaint(); 329 | return null; 330 | } 331 | 332 | static const $Function __addOverlay = $Function(_addOverlay); 333 | static $Value? _addOverlay( 334 | Runtime runtime, 335 | $Value? target, 336 | List<$Value?> args, 337 | ) { 338 | final self = target! as $EveryDoorApp; 339 | self.$value.addOverlay(args[0]!.$value); 340 | return null; 341 | } 342 | 343 | static const $Function __addMode = $Function(_addMode); 344 | static $Value? _addMode(Runtime runtime, $Value? target, List<$Value?> args) { 345 | final self = target! as $EveryDoorApp; 346 | self.$value.addMode(args[0]!.$value); 347 | return null; 348 | } 349 | 350 | static const $Function __removeMode = $Function(_removeMode); 351 | static $Value? _removeMode( 352 | Runtime runtime, 353 | $Value? target, 354 | List<$Value?> args, 355 | ) { 356 | final self = target! as $EveryDoorApp; 357 | self.$value.removeMode(args[0]!.$value); 358 | return null; 359 | } 360 | 361 | static const $Function __eachMode = $Function(_eachMode); 362 | static $Value? _eachMode( 363 | Runtime runtime, 364 | $Value? target, 365 | List<$Value?> args, 366 | ) { 367 | final self = target! as $EveryDoorApp; 368 | self.$value.eachMode((BaseModeDefinition arg0) { 369 | return (args[0]! as EvalCallable)(runtime, null, [ 370 | $BaseModeDefinition.wrap(arg0), 371 | ])?.$value; 372 | }); 373 | return null; 374 | } 375 | 376 | static const $Function __addAuthProvider = $Function(_addAuthProvider); 377 | static $Value? _addAuthProvider( 378 | Runtime runtime, 379 | $Value? target, 380 | List<$Value?> args, 381 | ) { 382 | final self = target! as $EveryDoorApp; 383 | self.$value.addAuthProvider(args[0]!.$value, args[1]!.$value); 384 | return null; 385 | } 386 | 387 | static const $Function __auth = $Function(_auth); 388 | static $Value? _auth(Runtime runtime, $Value? target, List<$Value?> args) { 389 | final self = target! as $EveryDoorApp; 390 | final result = self.$value.auth(args[0]!.$value); 391 | return $AuthController.wrap(result); 392 | } 393 | 394 | @override 395 | void $setProperty(Runtime runtime, String identifier, $Value value) { 396 | return _superclass.$setProperty(runtime, identifier, value); 397 | } 398 | } 399 | --------------------------------------------------------------------------------