Преглед на файлове

add linter and bump version to 0.2.0

Lejard Hadrien преди 7 години
родител
ревизия
4e49f098be
променени са 6 файла, в които са добавени 232 реда и са изтрити 96 реда
  1. 11 0
      CHANGELOG.md
  2. 120 1
      analysis_options.yaml
  3. 31 30
      example/lib/main.dart
  4. 51 50
      lib/src/base.dart
  5. 17 13
      lib/src/webview_scaffold.dart
  6. 2 2
      pubspec.yaml

+ 11 - 0
CHANGELOG.md

@@ -1,3 +1,14 @@
+# 0.2.0
+
+- update sdk
+- prevent negative webview height in scaffold
+- handle type error in getCookies
+- Support file upload via WebView on Android
+- fix WebviewScaffold crash on iOS
+- Scrollbar functionality to Web view
+- Add support of HTTP errors
+- Add headers when loading url
+
 # 0.1.6
 
 - fix onStateChanged

+ 120 - 1
analysis_options.yaml

@@ -1,2 +1,121 @@
 analyzer:
-  strong-mode: true
+
+linter:
+  rules:
+  # these rules are documented on and in the same order as
+  # the Dart Lint rules page to make maintenance easier
+  # https://github.com/dart-lang/linter/blob/master/example/all.yaml
+  - always_declare_return_types
+  - always_put_control_body_on_new_line
+  # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219
+  - always_require_non_null_named_parameters
+  # - always_specify_types
+  - annotate_overrides
+  # - avoid_annotating_with_dynamic # conflicts with always_specify_types
+  - avoid_as
+  # - avoid_bool_literals_in_conditional_expressions # not yet tested
+  # - avoid_catches_without_on_clauses # we do this commonly
+  # - avoid_catching_errors # we do this commonly
+  - avoid_classes_with_only_static_members
+  # - avoid_double_and_int_checks # only useful when targeting JS runtime
+  - avoid_empty_else
+  - avoid_field_initializers_in_const_classes
+  # - avoid_function_literals_in_foreach_calls
+  - avoid_init_to_null
+  # - avoid_js_rounded_ints # only useful when targeting JS runtime
+  - avoid_null_checks_in_equality_operators
+  # - avoid_positional_boolean_parameters # not yet tested
+  # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356)
+  - avoid_relative_lib_imports
+  - avoid_renaming_method_parameters
+  - avoid_return_types_on_setters
+  # - avoid_returning_null # we do this commonly
+  # - avoid_returning_this # https://github.com/dart-lang/linter/issues/842
+  # - avoid_setters_without_getters # not yet tested
+  # - avoid_single_cascade_in_expression_statements # not yet tested
+  - avoid_slow_async_io
+  # - avoid_types_as_parameter_names # https://github.com/dart-lang/linter/pull/954/files
+  # - avoid_types_on_closure_parameters # conflicts with always_specify_types
+  # - avoid_unused_constructor_parameters # https://github.com/dart-lang/linter/pull/847
+  - await_only_futures
+  - camel_case_types
+  - cancel_subscriptions
+  # - cascade_invocations # not yet tested
+  # - close_sinks # https://github.com/flutter/flutter/issues/5789
+  # - comment_references # blocked on https://github.com/dart-lang/dartdoc/issues/1153
+  # - constant_identifier_names # https://github.com/dart-lang/linter/issues/204
+  - control_flow_in_finally
+  - directives_ordering
+  - empty_catches
+  - empty_constructor_bodies
+  - empty_statements
+  - hash_and_equals
+  - implementation_imports
+  # - invariant_booleans # https://github.com/flutter/flutter/issues/5790
+  - iterable_contains_unrelated_type
+  # - join_return_with_assignment # not yet tested
+  - library_names
+  - library_prefixes
+  - list_remove_unrelated_type
+  # - literal_only_boolean_expressions # https://github.com/flutter/flutter/issues/5791
+  - no_adjacent_strings_in_list
+  - no_duplicate_case_values
+  - non_constant_identifier_names
+  # - omit_local_variable_types # opposite of always_specify_types
+  # - one_member_abstracts # too many false positives
+  # - only_throw_errors # https://github.com/flutter/flutter/issues/5792
+  - overridden_fields
+  - package_api_docs
+  - package_names
+  - package_prefixed_library_names
+  # - parameter_assignments # we do this commonly
+  - prefer_adjacent_string_concatenation
+  - prefer_asserts_in_initializer_lists
+  - prefer_bool_in_asserts
+  - prefer_collection_literals
+  - prefer_conditional_assignment
+  - prefer_const_constructors
+  - prefer_const_constructors_in_immutables
+  - prefer_const_declarations
+  - prefer_const_literals_to_create_immutables
+  # - prefer_constructors_over_static_methods # not yet tested
+  - prefer_contains
+  - prefer_equal_for_default_values
+  # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods
+  - prefer_final_fields
+  - prefer_final_locals
+  # - prefer_foreach
+  # - prefer_function_declarations_over_variables # not yet tested
+  - prefer_initializing_formals
+  # - prefer_interpolation_to_compose_strings # not yet tested
+  # - prefer_iterable_whereType # https://github.com/dart-lang/sdk/issues/32463
+  - prefer_is_empty
+  - prefer_is_not_empty
+  - prefer_single_quotes
+  - prefer_typing_uninitialized_variables
+  - recursive_getters
+  - slash_for_doc_comments
+  - sort_constructors_first
+  - sort_unnamed_constructors_first
+  - super_goes_last
+  - test_types_in_equals
+  - throw_in_finally
+  # - type_annotate_public_apis # subset of always_specify_types
+  - type_init_formals
+  # - unawaited_futures # https://github.com/flutter/flutter/issues/5793
+  - unnecessary_brace_in_string_interps
+  - unnecessary_getters_setters
+  # - unnecessary_lambdas # https://github.com/dart-lang/linter/issues/498
+  - unnecessary_null_aware_assignments
+  - unnecessary_null_in_if_null_operators
+  - unnecessary_overrides
+  - unnecessary_parenthesis
+  # - unnecessary_statements # not yet tested
+  - unnecessary_this
+  - unrelated_type_equality_checks
+  - use_rethrow_when_possible
+  # - use_setters_to_change_properties # not yet tested
+  # - use_string_buffers # https://github.com/dart-lang/linter/pull/664
+  # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review
+  - valid_regexps
+  # - void_checks # not yet tested

+ 31 - 30
example/lib/main.dart

@@ -5,9 +5,9 @@ import 'package:flutter/material.dart';
 import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
 
 const kAndroidUserAgent =
-    "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Mobile Safari/537.36";
+    'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Mobile Safari/537.36';
 
-String selectedUrl = "https://flutter.io";
+String selectedUrl = 'https://flutter.io';
 
 void main() {
   runApp(new MyApp());
@@ -22,11 +22,11 @@ class MyApp extends StatelessWidget {
         primarySwatch: Colors.blue,
       ),
       routes: {
-        "/": (_) => new MyHomePage(title: "Flutter WebView Demo"),
-        "/widget": (_) => new WebviewScaffold(
+        '/': (_) => const MyHomePage(title: 'Flutter WebView Demo'),
+        '/widget': (_) => new WebviewScaffold(
               url: selectedUrl,
               appBar: new AppBar(
-                title: new Text("Widget webview"),
+                title: const Text('Widget webview'),
               ),
               withZoom: true,
               withLocalStorage: true,
@@ -37,7 +37,7 @@ class MyApp extends StatelessWidget {
 }
 
 class MyHomePage extends StatefulWidget {
-  MyHomePage({Key key, this.title}) : super(key: key);
+  const MyHomePage({Key key, this.title}) : super(key: key);
 
   final String title;
 
@@ -60,17 +60,17 @@ class _MyHomePageState extends State<MyHomePage> {
 
   StreamSubscription<WebViewHttpError> _onHttpError;
 
-  TextEditingController _urlCtrl = new TextEditingController(text: selectedUrl);
+  final _urlCtrl = new TextEditingController(text: selectedUrl);
 
-  TextEditingController _codeCtrl =
-      new TextEditingController(text: "window.navigator.userAgent");
+  final _codeCtrl =
+      new TextEditingController(text: 'window.navigator.userAgent');
 
-  GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey();
+  final _scaffoldKey = new GlobalKey<ScaffoldState>();
 
   final _history = [];
 
   @override
-  initState() {
+  void initState() {
     super.initState();
 
     flutterWebviewPlugin.close();
@@ -83,8 +83,8 @@ class _MyHomePageState extends State<MyHomePage> {
     _onDestroy = flutterWebviewPlugin.onDestroy.listen((_) {
       if (mounted) {
         // Actions like show a info toast.
-        _scaffoldKey.currentState
-            .showSnackBar(new SnackBar(content: new Text("Webview Destroyed")));
+        _scaffoldKey.currentState.showSnackBar(
+            const SnackBar(content: const Text('Webview Destroyed')));
       }
     });
 
@@ -92,7 +92,7 @@ class _MyHomePageState extends State<MyHomePage> {
     _onUrlChanged = flutterWebviewPlugin.onUrlChanged.listen((String url) {
       if (mounted) {
         setState(() {
-          _history.add("onUrlChanged: $url");
+          _history.add('onUrlChanged: $url');
         });
       }
     });
@@ -101,15 +101,16 @@ class _MyHomePageState extends State<MyHomePage> {
         flutterWebviewPlugin.onStateChanged.listen((WebViewStateChanged state) {
       if (mounted) {
         setState(() {
-          _history.add("onStateChanged: ${state.type} ${state.url}");
+          _history.add('onStateChanged: ${state.type} ${state.url}');
         });
       }
     });
 
-    _onHttpError = flutterWebviewPlugin.onHttpError.listen((WebViewHttpError error) {
+    _onHttpError =
+        flutterWebviewPlugin.onHttpError.listen((WebViewHttpError error) {
       if (mounted) {
         setState(() {
-          _history.add("onHttpError: ${error.code} ${error.url}");
+          _history.add('onHttpError: ${error.code} ${error.url}');
         });
       }
     });
@@ -133,7 +134,7 @@ class _MyHomePageState extends State<MyHomePage> {
     return new Scaffold(
       key: _scaffoldKey,
       appBar: new AppBar(
-        title: new Text('Plugin example app'),
+        title: const Text('Plugin example app'),
       ),
       body: new Column(
         mainAxisAlignment: MainAxisAlignment.center,
@@ -149,25 +150,25 @@ class _MyHomePageState extends State<MyHomePage> {
                       0.0, 0.0, MediaQuery.of(context).size.width, 300.0),
                   userAgent: kAndroidUserAgent);
             },
-            child: new Text("Open Webview (rect)"),
+            child: const Text('Open Webview (rect)'),
           ),
           new RaisedButton(
             onPressed: () {
               flutterWebviewPlugin.launch(selectedUrl, hidden: true);
             },
-            child: new Text("Open 'hidden' Webview"),
+            child: const Text('Open "hidden" Webview'),
           ),
           new RaisedButton(
             onPressed: () {
               flutterWebviewPlugin.launch(selectedUrl);
             },
-            child: new Text("Open Fullscreen Webview"),
+            child: const Text('Open Fullscreen Webview'),
           ),
           new RaisedButton(
             onPressed: () {
-              Navigator.of(context).pushNamed("/widget");
+              Navigator.of(context).pushNamed('/widget');
             },
-            child: new Text("Open widget webview"),
+            child: const Text('Open widget webview'),
           ),
           new Container(
             padding: const EdgeInsets.all(24.0),
@@ -175,15 +176,15 @@ class _MyHomePageState extends State<MyHomePage> {
           ),
           new RaisedButton(
             onPressed: () {
-              Future<String> future =
+              final future =
                   flutterWebviewPlugin.evalJavascript(_codeCtrl.text);
               future.then((String result) {
                 setState(() {
-                  _history.add("eval: $result");
+                  _history.add('eval: $result');
                 });
               });
             },
-            child: new Text("Eval some javascript"),
+            child: const Text('Eval some javascript'),
           ),
           new RaisedButton(
             onPressed: () {
@@ -192,19 +193,19 @@ class _MyHomePageState extends State<MyHomePage> {
               });
               flutterWebviewPlugin.close();
             },
-            child: new Text("Close"),
+            child: const Text('Close'),
           ),
           new RaisedButton(
             onPressed: () {
               flutterWebviewPlugin.getCookies().then((m) {
                 setState(() {
-                  _history.add("cookies: $m");
+                  _history.add('cookies: $m');
                 });
               });
             },
-            child: new Text("Cookies"),
+            child: const Text('Cookies'),
           ),
-          new Text(_history.join("\n"))
+          new Text(_history.join('\n'))
         ],
       ),
     );

+ 51 - 50
lib/src/base.dart

@@ -31,20 +31,21 @@ class FlutterWebviewPlugin {
 
   Future<Null> _handleMessages(MethodCall call) async {
     switch (call.method) {
-      case "onDestroy":
+      case 'onDestroy':
         _onDestroy.add(null);
         break;
-      case "onUrlChanged":
-        _onUrlChanged.add(call.arguments["url"]);
+      case 'onUrlChanged':
+        _onUrlChanged.add(call.arguments['url']);
         break;
-      case "onState":
+      case 'onState':
         _onStateChanged.add(
           new WebViewStateChanged.fromMap(
               new Map<String, dynamic>.from(call.arguments)),
         );
         break;
-      case "onHttpError":
-        _onHttpError.add(WebViewHttpError(call.arguments['code'], call.arguments['url']));
+      case 'onHttpError':
+        _onHttpError.add(
+            WebViewHttpError(call.arguments['code'], call.arguments['url']));
         break;
     }
   }
@@ -93,30 +94,30 @@ class FlutterWebviewPlugin {
       bool withLocalStorage,
       bool withLocalUrl,
       bool scrollBar}) async {
-    Map<String, dynamic> args = {
-      "url": url,
-      "withJavascript": withJavascript ?? true,
-      "clearCache": clearCache ?? false,
-      "hidden": hidden ?? false,
-      "clearCookies": clearCookies ?? false,
-      "enableAppScheme": enableAppScheme ?? true,
-      "userAgent": userAgent,
-      "withZoom": withZoom ?? false,
-      "withLocalStorage": withLocalStorage ?? true,
-      "withLocalUrl": withLocalUrl ?? false,
-      "scrollBar": scrollBar ?? true
+    final args = <String, dynamic>{
+      'url': url,
+      'withJavascript': withJavascript ?? true,
+      'clearCache': clearCache ?? false,
+      'hidden': hidden ?? false,
+      'clearCookies': clearCookies ?? false,
+      'enableAppScheme': enableAppScheme ?? true,
+      'userAgent': userAgent,
+      'withZoom': withZoom ?? false,
+      'withLocalStorage': withLocalStorage ?? true,
+      'withLocalUrl': withLocalUrl ?? false,
+      'scrollBar': scrollBar ?? true
     };
 
     if (headers != null) {
-      args["headers"] = headers;
+      args['headers'] = headers;
     }
 
     if (rect != null) {
-      args["rect"] = {
-        "left": rect.left,
-        "top": rect.top,
-        "width": rect.width,
-        "height": rect.height
+      args['rect'] = {
+        'left': rect.left,
+        'top': rect.top,
+        'width': rect.width,
+        'height': rect.height
       };
     }
     await _channel.invokeMethod('launch', args);
@@ -124,47 +125,47 @@ class FlutterWebviewPlugin {
 
   /// Execute Javascript inside webview
   Future<String> evalJavascript(String code) async {
-    final res = await _channel.invokeMethod('eval', {"code": code});
+    final res = await _channel.invokeMethod('eval', {'code': code});
     return res;
   }
 
   /// Close the Webview
   /// Will trigger the [onDestroy] event
-  Future close() => _channel.invokeMethod("close");
+  Future close() => _channel.invokeMethod('close');
 
   /// Reloads the WebView.
   /// This is only available on Android for now.
-  Future reload() => _channel.invokeMethod("reload");
+  Future reload() => _channel.invokeMethod('reload');
 
   /// Navigates back on the Webview.
   /// This is only available on Android for now.
-  Future goBack() => _channel.invokeMethod("back");
+  Future goBack() => _channel.invokeMethod('back');
 
   /// Navigates forward on the Webview.
   /// This is only available on Android for now.
-  Future goForward() => _channel.invokeMethod("forward");
+  Future goForward() => _channel.invokeMethod('forward');
 
   // Hides the webview
-  Future hide() => _channel.invokeMethod("hide");
+  Future hide() => _channel.invokeMethod('hide');
 
   // Shows the webview
-  Future show() => _channel.invokeMethod("show");
+  Future show() => _channel.invokeMethod('show');
 
   // Reload webview with a new url
   Future reloadUrl(String url) async {
-    Map<String, dynamic> args = {
-      "url": url
-    };
-    await _channel.invokeMethod("reloadUrl", args);
+    final args = <String, String>{'url': url};
+    await _channel.invokeMethod('reloadUrl', args);
   }
 
   /// adds the plugin as ActivityResultListener
   /// Only needed and used on Android
-  Future registerAcitivityResultListener() => _channel.invokeMethod("registerAcitivityResultListener");
+  Future registerAcitivityResultListener() =>
+      _channel.invokeMethod('registerAcitivityResultListener');
 
   /// removes the plugin as ActivityResultListener
   /// Only needed and used on Android
-  Future removeAcitivityResultListener() => _channel.invokeMethod("removeAcitivityResultListener");
+  Future removeAcitivityResultListener() =>
+      _channel.invokeMethod('removeAcitivityResultListener');
 
   /// Close all Streams
   void dispose() {
@@ -176,12 +177,12 @@ class FlutterWebviewPlugin {
   }
 
   Future<Map<String, String>> getCookies() async {
-    final cookiesString = await evalJavascript("document.cookie");
+    final cookiesString = await evalJavascript('document.cookie');
     final cookies = <String, String>{};
 
     if (cookiesString?.isNotEmpty == true) {
-      cookiesString.split(";").forEach((String cookie) {
-        final splited = cookie.split("=");
+      cookiesString.split(';').forEach((String cookie) {
+        final splited = cookie.split('=');
         cookies[splited[0]] = splited[1];
       });
     }
@@ -192,11 +193,11 @@ class FlutterWebviewPlugin {
   /// resize webview
   Future<Null> resize(Rect rect) async {
     final args = {};
-    args["rect"] = {
-      "left": rect.left,
-      "top": rect.top,
-      "width": rect.width,
-      "height": rect.height
+    args['rect'] = {
+      'left': rect.left,
+      'top': rect.top,
+      'width': rect.width,
+      'height': rect.height
     };
     await _channel.invokeMethod('resize', args);
   }
@@ -211,18 +212,18 @@ class WebViewStateChanged {
 
   factory WebViewStateChanged.fromMap(Map<String, dynamic> map) {
     WebViewState t;
-    switch (map["type"]) {
-      case "shouldStart":
+    switch (map['type']) {
+      case 'shouldStart':
         t = WebViewState.shouldStart;
         break;
-      case "startLoad":
+      case 'startLoad':
         t = WebViewState.startLoad;
         break;
-      case "finishLoad":
+      case 'finishLoad':
         t = WebViewState.finishLoad;
         break;
     }
-    return new WebViewStateChanged(t, map["url"], map["navigationType"]);
+    return new WebViewStateChanged(t, map['url'], map['navigationType']);
   }
 }
 

+ 17 - 13
lib/src/webview_scaffold.dart

@@ -6,7 +6,6 @@ import 'package:flutter/material.dart';
 import 'base.dart';
 
 class WebviewScaffold extends StatefulWidget {
-
   final PreferredSizeWidget appBar;
   final String url;
   final bool withJavascript;
@@ -24,7 +23,7 @@ class WebviewScaffold extends StatefulWidget {
 
   final Map<String, String> headers;
 
-  WebviewScaffold(
+  const WebviewScaffold(
       {Key key,
       this.appBar,
       @required this.url,
@@ -34,7 +33,7 @@ class WebviewScaffold extends StatefulWidget {
       this.clearCookies,
       this.enableAppScheme,
       this.userAgent,
-      this.primary: true,
+      this.primary = true,
       this.persistentFooterButtons,
       this.bottomNavigationBar,
       this.withZoom,
@@ -52,11 +51,13 @@ class _WebviewScaffoldState extends State<WebviewScaffold> {
   Rect _rect;
   Timer _resizeTimer;
 
+  @override
   void initState() {
     super.initState();
     webviewReference.close();
   }
 
+  @override
   void dispose() {
     super.dispose();
     webviewReference.close();
@@ -80,7 +81,7 @@ class _WebviewScaffoldState extends State<WebviewScaffold> {
           withLocalUrl: widget.withLocalUrl,
           scrollBar: widget.scrollBar);
     } else {
-      Rect rect = _buildRect(context);
+      final rect = _buildRect(context);
       if (_rect != rect) {
         _rect = rect;
         _resizeTimer?.cancel();
@@ -94,33 +95,36 @@ class _WebviewScaffoldState extends State<WebviewScaffold> {
         appBar: widget.appBar,
         persistentFooterButtons: widget.persistentFooterButtons,
         bottomNavigationBar: widget.bottomNavigationBar,
-        body: new Center(child: new CircularProgressIndicator()));
+        body: const Center(child: const CircularProgressIndicator()));
   }
 
   Rect _buildRect(BuildContext context) {
-    bool fullscreen = widget.appBar == null;
+    final fullscreen = widget.appBar == null;
 
     final mediaQuery = MediaQuery.of(context);
     final topPadding = widget.primary ? mediaQuery.padding.top : 0.0;
-    num top =
+    final top =
         fullscreen ? 0.0 : widget.appBar.preferredSize.height + topPadding;
 
-    num height = mediaQuery.size.height - top;
+    var height = mediaQuery.size.height - top;
 
     if (widget.bottomNavigationBar != null) {
-      height -=
-          56.0 + mediaQuery.padding.bottom; // todo(lejard_h) find a way to determine bottomNavigationBar programmatically
+      height -= 56.0 +
+          mediaQuery.padding
+              .bottom; // todo(lejard_h) find a way to determine bottomNavigationBar programmatically
     }
 
     if (widget.persistentFooterButtons != null) {
       height -=
           53.0; // todo(lejard_h) find a way to determine persistentFooterButtons programmatically
-      if (widget.bottomNavigationBar == null){
-         height -= mediaQuery.padding.bottom;
+      if (widget.bottomNavigationBar == null) {
+        height -= mediaQuery.padding.bottom;
       }
     }
 
-    if (height < 0.0) height = 0.0;
+    if (height < 0.0) {
+      height = 0.0;
+    }
 
     return new Rect.fromLTWH(0.0, top, mediaQuery.size.width, height);
   }

+ 2 - 2
pubspec.yaml

@@ -5,10 +5,10 @@ authors:
 - Toufik Zitouni <toufiksapps@gmail.com>
 - Pedia <kpedia@163.com>
 homepage: https://github.com/dart-flitter/flutter_webview_plugin
-version: 0.1.6
+version: 0.2.0
 
 environment:
-  sdk: ">=1.19.0 <2.0.0"
+  sdk: ">=2.0.0-dev <3.0.0"
 
 flutter:
   plugin: