Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schema #19

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

10 changes: 9 additions & 1 deletion example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,14 @@
files = (
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../../../../../flutter/bin/cache/artifacts/engine/ios/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/flutter_webview_plugin/flutter_webview_plugin.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_webview_plugin.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
Expand All @@ -286,13 +291,16 @@
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
Expand Down
83 changes: 66 additions & 17 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,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";

void main() {
runApp(new MyApp());
}
Expand Down Expand Up @@ -32,16 +35,22 @@ class MyHomePage extends StatefulWidget {

class _MyHomePageState extends State<MyHomePage> {
// Instance of WebView plugin
final FlutterWebviewPlugin flutterWebviewPlugin = new FlutterWebviewPlugin();
final FlutterWebViewPlugin flutterWebviewPlugin = new FlutterWebViewPlugin();

// On destroy stream
StreamSubscription _onDestroy;

// On urlChanged stream
StreamSubscription<String> _onUrlChanged;

TextEditingController _ctrl =
new TextEditingController(text: "https://flutter.io");
StreamSubscription<String> _onStateChanged;

TextEditingController _urlCtrl =
new TextEditingController(text: "http://github.com");

TextEditingController _codeCtrl =
new TextEditingController(text: "window.navigator.userAgent");

GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey();

final _history = [];
Expand All @@ -50,6 +59,14 @@ class _MyHomePageState extends State<MyHomePage> {
initState() {
super.initState();

_onStateChanged = flutterWebviewPlugin.stateChanged.listen((dynamic state) {
if (mounted) {
setState(() {
_history.add("stateChanged: $state");
});
}
});

// Add a listener to on destroy WebView, so you can make came actions.
_onDestroy = flutterWebviewPlugin.onDestroy.listen((_) {
if (mounted) {
Expand All @@ -63,7 +80,7 @@ class _MyHomePageState extends State<MyHomePage> {
_onUrlChanged = flutterWebviewPlugin.onUrlChanged.listen((String url) {
if (mounted) {
setState(() {
_history.add(url);
_history.add("onUrlChanged: $url");
});
}
});
Expand All @@ -90,24 +107,56 @@ class _MyHomePageState extends State<MyHomePage> {
children: [
new Container(
padding: const EdgeInsets.all(24.0),
child: new TextField(controller: _ctrl),
child: new TextField(controller: _urlCtrl),
),
new RaisedButton(
onPressed: () {
flutterWebviewPlugin.launch(_urlCtrl.text,
fullScreen: false,
rect: new Rect.fromLTWH(
0.0, 0.0, MediaQuery.of(context).size.width, 300.0),
userAgent: kAndroidUserAgent);
},
child: new Text("Open Webview (rect)"),
),
new RaisedButton(
onPressed: _onPressed,
child: new Text("Open Webview"),
onPressed: () {
flutterWebviewPlugin.launch(_urlCtrl.text, hidden: true);
},
child: new Text("Open 'hidden' Webview"),
),
new Text(_history.join(", "))
new RaisedButton(
onPressed: () {
flutterWebviewPlugin.launch(_urlCtrl.text, fullScreen: true);
},
child: new Text("Open Fullscreen Webview"),
),
new Container(
padding: const EdgeInsets.all(24.0),
child: new TextField(controller: _codeCtrl),
),
new RaisedButton(
onPressed: () {
Future<String> future =
flutterWebviewPlugin.evalJavascript(_codeCtrl.text);
future.then((String result) {
setState(() {
_history.add("eval: $result");
});
});
},
child: new Text("Eval some javascript"),
),
new RaisedButton(
onPressed: () {
_history.clear();
flutterWebviewPlugin.close();
},
child: new Text("Close"),
),
new Text(_history.join("\n"))
],
),
);
}

void _onPressed() {
try {
// This way you launch WebView with an url as a parameter.
flutterWebviewPlugin.launch(_ctrl.text);
} catch (e) {
print(e);
}
}
}
2 changes: 1 addition & 1 deletion ios/Classes/FlutterWebviewPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ static FlutterMethodChannel *channel;

@interface FlutterWebviewPlugin : NSObject<FlutterPlugin>
@property (nonatomic, retain) UIViewController *viewController;
@property (nonatomic, retain) WebviewController *webviewController;
@property (nonatomic, retain) UIWebView *webview;
@end
141 changes: 128 additions & 13 deletions ios/Classes/FlutterWebviewPlugin.m
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
#import "FlutterWebviewPlugin.h"

static NSString *const CHANNEL_NAME = @"flutter_webview_plugin";
static NSString *const EVENT_CHANNEL_NAME = @"flutter_webview_plugin_event";

// UIWebViewDelegate
@interface FlutterWebviewPlugin() <UIWebViewDelegate, FlutterStreamHandler> {
FlutterEventSink _eventSink;
BOOL _enableAppScheme;
}
@end

@implementation FlutterWebviewPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
channel = [FlutterMethodChannel
methodChannelWithName:CHANNEL_NAME
binaryMessenger:[registrar messenger]];

UIViewController *viewController = (UIViewController *)registrar.messenger;
FlutterWebviewPlugin* instance = [[FlutterWebviewPlugin alloc] initWithViewController:viewController];

[registrar addMethodCallDelegate:instance channel:channel];

FlutterEventChannel* event =
[FlutterEventChannel eventChannelWithName:EVENT_CHANNEL_NAME
binaryMessenger:[registrar messenger]];
[event setStreamHandler:instance];
}

- (instancetype)initWithViewController:(UIViewController *)viewController {
Expand All @@ -22,37 +37,137 @@ - (instancetype)initWithViewController:(UIViewController *)viewController {

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
if ([@"launch" isEqualToString:call.method]) {
[self showWebView:call];
if (!self.webview)
[self initWebView:call];
else
[self launch:call];
result(nil);
} else if ([@"close" isEqualToString:call.method]) {
[self closeWebView];
result(nil);
} else if ([@"eval" isEqualToString:call.method]) {
result([self evalJavascript:call]);
} else {
result(FlutterMethodNotImplemented);
}
}

- (void)showWebView:(FlutterMethodCall*)call {
NSString *url = call.arguments[@"url"];
NSNumber *withJavascript = call.arguments[@"withJavascript"];
- (void)initWebView:(FlutterMethodCall*)call {
// NSNumber *withJavascript = call.arguments[@"withJavascript"];
NSNumber *clearCache = call.arguments[@"clearCache"];
NSNumber *clearCookies = call.arguments[@"clearCookies"];
NSNumber *fullScreen = call.arguments[@"fullScreen"];
NSNumber *hidden = call.arguments[@"hidden"];
NSDictionary *rect = call.arguments[@"rect"];
_enableAppScheme = call.arguments[@"enableAppScheme"];
NSString *userAgent = call.arguments[@"userAgent"];

self.webviewController = [[WebviewController alloc] initWithUrl:url withJavascript:withJavascript clearCache:clearCache clearCookes:clearCookies];
//
if ([clearCache boolValue]) {
[[NSURLCache sharedURLCache] removeAllCachedResponses];
}

if ([fullScreen boolValue]) {
[self.viewController presentViewController:self.webviewController animated:YES completion:nil];
if ([clearCookies boolValue]) {
[[NSURLSession sharedSession] resetWithCompletionHandler:^{
}];
}

CGRect rc;
if (rect) {
rc = CGRectMake([[rect valueForKey:@"left"] doubleValue],
[[rect valueForKey:@"top"] doubleValue],
[[rect valueForKey:@"width"] doubleValue],
[[rect valueForKey:@"height"] doubleValue]);
} else {
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:self.webviewController];
[self.viewController presentModalViewController:navigation animated:YES];
rc = self.viewController.view.bounds;
}

if (userAgent) {
[[NSUserDefaults standardUserDefaults] registerDefaults:@{@"UserAgent": userAgent}];
}

self.webview = [[UIWebView alloc] initWithFrame:rc];
self.webview.delegate = self;

if (!hidden || ![hidden boolValue])
[self.viewController.view addSubview:self.webview];

[self launch:call];
}

- (void)launch:(FlutterMethodCall*)call {
NSString *url = call.arguments[@"url"];

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
[self.webview loadRequest:request];
}

- (NSString *)evalJavascript:(FlutterMethodCall*)call {
NSString *code = call.arguments[@"code"];

NSString *result = [self.webview stringByEvaluatingJavaScriptFromString:code];
return result;
}

- (void)closeWebView {
[self.webviewController dismissViewControllerAnimated:YES completion:^{
[channel invokeMethod:@"onDestroy" arguments:nil];
}];
[self.webview stopLoading];
[self.webview removeFromSuperview];
self.webview.delegate = nil;
self.webview = nil;
[self sendEvent:@"destroy"];
}


#pragma mark -- WebView Delegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSArray *data = [NSArray arrayWithObjects:@"shouldStart",
request.URL.absoluteString, [NSNumber numberWithInt:navigationType],
nil];
[self sendEvent:data];

if (_enableAppScheme)
return YES;

// disable some scheme
return [request.URL.scheme isEqualToString:@"http"] ||
[request.URL.scheme isEqualToString:@"https"] ||
[request.URL.scheme isEqualToString:@"about"];
}

-(void)webViewDidStartLoad:(UIWebView *)webView {
[self sendEvent:@"startLoad"];
}

- (void)webViewDidFinishLoad:(UIWebView *)webView {
[self sendEvent:@"finishLoad"];
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
id data = [FlutterError errorWithCode:[NSString stringWithFormat:@"%ld", error.code]
message:error.localizedDescription
details:error.localizedFailureReason];
[self sendEvent:data];
}

#pragma mark -- WkWebView Delegate

#pragma mark -- FlutterStreamHandler impl

- (FlutterError*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink {
_eventSink = eventSink;
return nil;
}

- (FlutterError*)onCancelWithArguments:(id)arguments {
[[NSNotificationCenter defaultCenter] removeObserver:self];
_eventSink = nil;
return nil;
}

- (void)sendEvent:(id)data {
// data should be @"" or [FlutterError]
if (!_eventSink)
return;

_eventSink(data);
}
@end
Loading