diff --git a/packages/flutter_tools/templates/plugin/lib/projectName_web.dart.tmpl b/packages/flutter_tools/templates/plugin/lib/projectName_web.dart.tmpl new file mode 100644 index 00000000000..37dc71c4c53 --- /dev/null +++ b/packages/flutter_tools/templates/plugin/lib/projectName_web.dart.tmpl @@ -0,0 +1,45 @@ +import 'dart:async'; +// In order to *not* need this ignore, consider extracting the "web" version +// of your plugin as a separate package, instead of inlining it in the same +// package as the core of your plugin. +// ignore: avoid_web_libraries_in_flutter +import 'dart:html' as html show window; + +import 'package:flutter/services.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + +/// A web implementation of the {{pluginDartClass}} plugin. +class {{pluginDartClass}}Web { + static void registerWith(Registrar registrar) { + final MethodChannel channel = MethodChannel( + '{{projectName}}', + const StandardMethodCodec(), + registrar.messenger, + ); + + final pluginInstance = {{pluginDartClass}}Web(); + channel.setMethodCallHandler(pluginInstance.handleMethodCall); + } + + /// Handles method calls over the MethodChannel of this plugin. + /// Note: Check the "federated" architecture for a new way of doing this: + /// https://flutter.dev/go/federated-plugins + Future handleMethodCall(MethodCall call) async { + switch (call.method) { + case 'getPlatformVersion': + return getPlatformVersion(); + break; + default: + throw PlatformException( + code: 'Unimplemented', + details: '{{projectName}} for web doesn\'t implement \'${call.method}\'', + ); + } + } + + /// Returns a [String] containing the version of the platform. + Future getPlatformVersion() { + final version = html.window.navigator.userAgent; + return Future.value(version); + } +} diff --git a/packages/flutter_tools/templates/plugin/pubspec.yaml.tmpl b/packages/flutter_tools/templates/plugin/pubspec.yaml.tmpl index c215cb295ff..1cc1ca49598 100644 --- a/packages/flutter_tools/templates/plugin/pubspec.yaml.tmpl +++ b/packages/flutter_tools/templates/plugin/pubspec.yaml.tmpl @@ -11,6 +11,10 @@ environment: dependencies: flutter: sdk: flutter +{{#web}} + flutter_web_plugins: + sdk: flutter +{{/web}} dev_dependencies: flutter_test: @@ -40,6 +44,11 @@ flutter: macos: pluginClass: {{pluginClass}} {{/macos}} +{{#web}} + web: + pluginClass: {{pluginDartClass}}Web + fileName: {{projectName}}_web.dart +{{/web}} # To add assets to your plugin package, add an assets section, like this: # assets: diff --git a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart index 779fa65989f..b856d69ca29 100644 --- a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart +++ b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart @@ -391,6 +391,9 @@ void main() { 'ios/Classes/FlutterProjectPlugin.m', 'lib/flutter_project.dart', ], + unexpectedPaths: [ + 'lib/flutter_project_web.dart', + ], ); return _runFlutterTest(projectDir.childDirectory('example')); }, overrides: { @@ -404,6 +407,34 @@ void main() { ), }); + testUsingContext('plugin project supports web', () async { + await _createAndAnalyzeProject( + projectDir, + ['--template=plugin'], + [ + 'lib/flutter_project.dart', + 'lib/flutter_project_web.dart', + ], + ); + final String rawPubspec = await projectDir.childFile('pubspec.yaml').readAsString(); + final Pubspec pubspec = Pubspec.parse(rawPubspec); + // Expect the dependency on flutter_web_plugins exists + expect(pubspec.dependencies, contains('flutter_web_plugins')); + // The platform is correctly registered + expect(pubspec.flutter['plugin']['platforms']['web']['pluginClass'], 'FlutterProjectWeb'); + expect(pubspec.flutter['plugin']['platforms']['web']['fileName'], 'flutter_project_web.dart'); + }, overrides: { + FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), + Pub: () => Pub( + fileSystem: globals.fs, + logger: globals.logger, + processManager: globals.processManager, + usage: globals.flutterUsage, + botDetector: globals.botDetector, + platform: globals.platform, + ), + }); + testUsingContext('plugin example app depends on plugin', () async { await _createProject( projectDir,