-
Notifications
You must be signed in to change notification settings - Fork 9.7k
[webview_flutter] Implementations of loadFile and loadHtmlString for WKWebView
#4486
Changes from 1 commit
8e05ac2
c1dc83a
f1343c2
0351601
b945839
5218c0a
d5cf9f9
98eb236
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
Adds native implementation for the `loadFile` method channel call to the webview_flutter_wkwebview package.
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -305,6 +305,20 @@ class WebViewController { | |
|
|
||
| WebView _widget; | ||
|
|
||
| /// Loads the file located on the specified [absoluteFilePath]. | ||
| /// | ||
| /// The [absoluteFilePath] parameter should contain the absolute path to the | ||
| /// file as it is stored on the device. For example: | ||
| /// `/Users/username/Documents/www/index.html`. | ||
| /// | ||
| /// Throws an ArgumentError if the [absoluteFilePath] does not exist. | ||
| Future<void> loadFile( | ||
| String absoluteFilePath, | ||
| ) { | ||
| assert(absoluteFilePath != null || absoluteFilePath.isNotEmpty); | ||
|
||
| return _webViewPlatformController.loadFile(absoluteFilePath); | ||
| } | ||
|
|
||
| /// Loads the specified URL. | ||
| /// | ||
| /// If `headers` is not null and the URL is an HTTP URL, the key value paris in `headers` will | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -135,6 +135,8 @@ - (UIView*)view { | |
| - (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { | ||
| if ([[call method] isEqualToString:@"updateSettings"]) { | ||
| [self onUpdateSettings:call result:result]; | ||
| } else if ([[call method] isEqualToString:@"loadFile"]) { | ||
| [self onLoadFile:call result:result]; | ||
| } else if ([[call method] isEqualToString:@"loadUrl"]) { | ||
| [self onLoadUrl:call result:result]; | ||
| } else if ([[call method] isEqualToString:@"canGoBack"]) { | ||
|
|
@@ -185,6 +187,22 @@ - (void)onUpdateSettings:(FlutterMethodCall*)call result:(FlutterResult)result { | |
| result([FlutterError errorWithCode:@"updateSettings_failed" message:error details:nil]); | ||
| } | ||
|
|
||
| - (void)onLoadFile:(FlutterMethodCall*)call result:(FlutterResult)result { | ||
| NSString* error = nil; | ||
| if (![FLTWebViewController isValidStringArgument:[call arguments] withErrorMessage:&error]) { | ||
| result([FlutterError errorWithCode:@"loadFile_failed" | ||
| message:@"Failed parsing file path." | ||
| details:error]); | ||
| return; | ||
| } | ||
|
|
||
| NSURL* url = [NSURL fileURLWithPath:[call arguments] isDirectory:NO]; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should validate that this is non-nil before passing it below (returning an error if it is nil) in case someone passes a garbage string that doesn't parse as a path.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added additional check to ensure the |
||
| NSURL* baseUrl = [url URLByDeletingLastPathComponent]; | ||
|
|
||
| [_webView loadFileURL:url allowingReadAccessToURL:baseUrl]; | ||
| result(nil); | ||
| } | ||
|
|
||
| - (void)onLoadUrl:(FlutterMethodCall*)call result:(FlutterResult)result { | ||
| if (![self loadRequest:[call arguments]]) { | ||
| result([FlutterError | ||
|
|
@@ -517,6 +535,29 @@ - (void)updateUserAgent:(NSString*)userAgent { | |
| } | ||
| } | ||
|
|
||
| + (bool)isValidStringArgument:(id)argument withErrorMessage:(NSString**)errorDetails { | ||
|
||
| if (!argument) { | ||
| if (errorDetails) { | ||
| *errorDetails = @"Argument is nil."; | ||
| } | ||
| return NO; | ||
| } | ||
| if (![argument isKindOfClass:NSString.class]) { | ||
| if (errorDetails) { | ||
| *errorDetails = @"Argument is not of type NSString."; | ||
| } | ||
| return NO; | ||
| } | ||
| if (![argument length]) { | ||
| if (errorDetails) { | ||
| *errorDetails = @"Argument contains an empty string."; | ||
| } | ||
| return NO; | ||
| } | ||
|
|
||
| return YES; | ||
| } | ||
|
|
||
| #pragma mark WKUIDelegate | ||
|
|
||
| - (WKWebView*)webView:(WKWebView*)webView | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This early return seems odd; why would we want not changes someone made locally to the example HTML (e.g., to try to reproduce an issue in the context of the example) after having already run once to take effect?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. I added this check with the idea that if the file exists we don't have to write it again (in case the user presses the button twice in the same session). However I didn't think about the fact that the file will be persisted over multiple sessions and developers might want to change the HTML contents.