Skip to content
Merged
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
7 changes: 7 additions & 0 deletions packages/webview_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 0.10.0

* Update minimum supported SDK version to Flutter 3.32/Dart 3.8.
* Update webview_flutter to 4.13.1.
* Update webview_flutter_platform_interface to 2.13.0.
* Add support for setVerticalScrollBarEnabled, setHorizontalScrollBarEnabled, supportsSetScrollBarsEnabled APIs

## 0.9.7

* Fix back key, exit key handling.
Expand Down
15 changes: 13 additions & 2 deletions packages/webview_flutter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ This package is not an _endorsed_ implementation of `webview_flutter`. Therefore

```yaml
dependencies:
webview_flutter: ^4.10.0
webview_flutter_tizen: ^0.9.7
webview_flutter: ^4.13.1
webview_flutter_tizen: ^0.10.0
```

## Example
Expand Down Expand Up @@ -85,3 +85,14 @@ import 'package:webview_flutter_tizen/webview_flutter_tizen.dart';
WebViewController _controller;
_controller.tizenEnginePolicy = true;
```

- The `setVerticalScrollBarEnabled` and `setHorizontalScrollBarEnabled` methods are not independently controllable. Calling either method will affect both vertical and horizontal scrollbars simultaneously.
If you need to hide scrollbars, call only one of these methods with `false`. Setting different values for each scrollbar (e.g., vertical enabled but horizontal disabled) is not supported. Note that these methods are currently not supported on TV devices. We are working on adding support in the near future.

```dart
// This will hide both vertical and horizontal scrollbars
await controller.setVerticalScrollBarEnabled(false);

// This will show both vertical and horizontal scrollbars
await controller.setHorizontalScrollBarEnabled(true);
```
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,11 @@ Future<void> main() async {

await pageLoads.stream.firstWhere((String url) => url == headersUrl);

final String content = await controller.runJavaScriptReturningResult(
'document.documentElement.innerText',
) as String;
final String content =
await controller.runJavaScriptReturningResult(
'document.documentElement.innerText',
)
as String;
expect(content.contains('flutter_test_header'), isTrue);
});

Expand Down Expand Up @@ -309,7 +311,8 @@ Future<void> main() async {

group('NavigationDelegate', () {
const String blankPage = '<!DOCTYPE html><head></head><body></body></html>';
final String blankPageEncoded = 'data:text/html;charset=utf-8;base64,'
final String blankPageEncoded =
'data:text/html;charset=utf-8;base64,'
'${base64Encode(const Utf8Encoder().convert(blankPage))}';

testWidgets('can allow requests', (WidgetTester tester) async {
Expand Down
5 changes: 3 additions & 2 deletions packages/webview_flutter/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -453,8 +453,9 @@ class SampleMenu extends StatelessWidget {
}

Future<void> _onListCookies(BuildContext context) async {
final String cookies = await webViewController
.runJavaScriptReturningResult('document.cookie') as String;
final String cookies =
await webViewController.runJavaScriptReturningResult('document.cookie')
as String;
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
Expand Down
6 changes: 3 additions & 3 deletions packages/webview_flutter/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ description: Demonstrates how to use the webview_flutter_tizen plugin.
publish_to: "none"

environment:
sdk: ^3.5.0
flutter: ">=3.24.0"
sdk: ^3.8.0
flutter: ">=3.32.0"

dependencies:
flutter:
sdk: flutter
path_provider: ^2.0.7
path_provider_tizen:
path: ../../path_provider/
webview_flutter: ^4.10.0
webview_flutter: ^4.13.0
webview_flutter_tizen:
path: ../

Expand Down
13 changes: 10 additions & 3 deletions packages/webview_flutter/lib/src/tizen_webview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,8 @@ class TizenWebView {
Future<Offset> getScrollPosition() async {
final Map<String, Object?>? position =
(await _invokeChannelMethod<Map<Object?, Object?>>(
'getScrollPosition',
))
?.cast<String, Object?>();
'getScrollPosition',
))?.cast<String, Object?>();
if (position == null) {
return Offset.zero;
}
Expand Down Expand Up @@ -242,4 +241,12 @@ class TizenWebView {
/// Sets the value selected by the user input
Future<void> javaScriptPromptReply(String result) =>
_invokeChannelMethod<void>('javaScriptPromptReply', result);

/// Whether the vertical scrollbar should be drawn or not.
Future<void> setVerticalScrollBarEnabled(bool enabled) =>
_invokeChannelMethod<void>('setVerticalScrollBarEnabled', enabled);

/// Whether the horizontal scrollbar should be drawn or not.
Future<void> setHorizontalScrollBarEnabled(bool enabled) =>
_invokeChannelMethod<void>('setHorizontalScrollBarEnabled', enabled);
}
74 changes: 51 additions & 23 deletions packages/webview_flutter/lib/src/tizen_webview_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,20 @@ extension TizenWebViewControllerExtension on WebViewController {
class TizenWebViewController extends PlatformWebViewController {
/// Constructs a [TizenWebViewController].
TizenWebViewController(super.params)
: _webview = TizenWebView(),
super.implementation();
: _webview = TizenWebView(),
super.implementation();

final TizenWebView _webview;
late TizenNavigationDelegate _tizenNavigationDelegate;

void Function(JavaScriptConsoleMessage consoleMessage)? _onConsoleLogCallback;

Future<void> Function(JavaScriptAlertDialogRequest request)?
_onJavaScriptAlert;
_onJavaScriptAlert;
Future<bool> Function(JavaScriptConfirmDialogRequest request)?
_onJavaScriptConfirm;
_onJavaScriptConfirm;
Future<String> Function(JavaScriptTextInputDialogRequest request)?
_onJavaScriptPrompt;
_onJavaScriptPrompt;

late final MethodChannel _webviewControllerChannel;

Expand Down Expand Up @@ -93,37 +93,37 @@ class TizenWebViewController extends PlatformWebViewController {
if (callback != null) {
final JavaScriptAlertDialogRequest request =
JavaScriptAlertDialogRequest(
message: arguments['message']! as String,
url: arguments['url']! as String,
);
message: arguments['message']! as String,
url: arguments['url']! as String,
);

await callback.call(request);
await _webview.javaScriptAlertReply();
}
return null;
case 'onJavaScriptConfirm':
final Future<bool> Function(JavaScriptConfirmDialogRequest)?
callback = _onJavaScriptConfirm;
callback = _onJavaScriptConfirm;
if (callback != null) {
final JavaScriptConfirmDialogRequest request =
JavaScriptConfirmDialogRequest(
message: arguments['message']! as String,
url: arguments['url']! as String,
);
message: arguments['message']! as String,
url: arguments['url']! as String,
);
final bool result = await callback.call(request);
await _webview.javaScriptConfirmReply(result);
}
return null;
case 'onJavaScriptPrompt':
final Future<String> Function(JavaScriptTextInputDialogRequest)?
callback = _onJavaScriptPrompt;
callback = _onJavaScriptPrompt;
if (callback != null) {
final JavaScriptTextInputDialogRequest request =
JavaScriptTextInputDialogRequest(
message: arguments['message']! as String,
url: arguments['url']! as String,
defaultText: arguments['defaultText']! as String,
);
message: arguments['message']! as String,
url: arguments['url']! as String,
defaultText: arguments['defaultText']! as String,
);
final String result = await callback.call(request);
await _webview.javaScriptPromptReply(result);
}
Expand Down Expand Up @@ -248,8 +248,7 @@ class TizenWebViewController extends PlatformWebViewController {
@override
Future<void> addJavaScriptChannel(
JavaScriptChannelParams javaScriptChannelParams,
) =>
_webview.addJavaScriptChannel(javaScriptChannelParams);
) => _webview.addJavaScriptChannel(javaScriptChannelParams);

@override
Future<void> removeJavaScriptChannel(String javaScriptChannelName) async {
Expand Down Expand Up @@ -289,7 +288,7 @@ class TizenWebViewController extends PlatformWebViewController {
@override
Future<void> setOnScrollPositionChange(
void Function(ScrollPositionChange scrollPositionChange)?
onScrollPositionChange,
onScrollPositionChange,
) async {
throw UnimplementedError(
'This version of `TizenWebViewController` currently has no '
Expand Down Expand Up @@ -322,26 +321,47 @@ class TizenWebViewController extends PlatformWebViewController {
@override
Future<void> setOnJavaScriptAlertDialog(
Future<void> Function(JavaScriptAlertDialogRequest request)
onJavaScriptAlertDialog,
onJavaScriptAlertDialog,
) async {
_onJavaScriptAlert = onJavaScriptAlertDialog;
}

@override
Future<void> setOnJavaScriptConfirmDialog(
Future<bool> Function(JavaScriptConfirmDialogRequest request)
onJavaScriptConfirmDialog,
onJavaScriptConfirmDialog,
) async {
_onJavaScriptConfirm = onJavaScriptConfirmDialog;
}

@override
Future<void> setOnJavaScriptTextInputDialog(
Future<String> Function(JavaScriptTextInputDialogRequest request)
onJavaScriptTextInputDialog,
onJavaScriptTextInputDialog,
) async {
_onJavaScriptPrompt = onJavaScriptTextInputDialog;
}

@override
Future<void> setVerticalScrollBarEnabled(bool enabled) {
return _webview.setVerticalScrollBarEnabled(enabled);
}

@override
Future<void> setHorizontalScrollBarEnabled(bool enabled) {
return _webview.setHorizontalScrollBarEnabled(enabled);
}

@override
bool supportsSetScrollBarsEnabled() => true;

@override
Future<void> setOverScrollMode(WebViewOverScrollMode mode) async {
throw UnimplementedError(
'This version of `TizenWebViewController` currently has no '
'implementation of `setOverScrollMode`.',
);
}
}

/// An implementation of [PlatformWebViewWidget] with the Tizen WebView API.
Expand Down Expand Up @@ -592,4 +612,12 @@ class TizenNavigationDelegate extends PlatformNavigationDelegate {
'implementation for `setOnHttpAuthRequest`',
);
}

@override
Future<void> setOnSSlAuthError(SslAuthErrorCallback onSslAuthError) {
throw UnimplementedError(
'This version of `TizenNavigationDelegate` currently has no '
'implementation for `setOnSSlAuthError`',
);
}
}
10 changes: 5 additions & 5 deletions packages/webview_flutter/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ name: webview_flutter_tizen
description: Tizen implementation of the webview_flutter plugin.
homepage: https://github.com/flutter-tizen/plugins
repository: https://github.com/flutter-tizen/plugins/tree/master/packages/webview_flutter
version: 0.9.7
version: 0.10.0

environment:
sdk: ">=3.1.0 <4.0.0"
flutter: ">=3.13.0"
sdk: ^3.8.0
flutter: ">=3.32.0"

flutter:
plugin:
Expand All @@ -20,8 +20,8 @@ dependencies:
flutter:
sdk: flutter
flutter_tizen: ^0.2.1
webview_flutter: ^4.4.2
webview_flutter_platform_interface: ^2.6.0
webview_flutter: ^4.13.1
webview_flutter_platform_interface: ^2.13.0

topics:
- html
Expand Down
13 changes: 9 additions & 4 deletions packages/webview_flutter/tizen/src/ewk_internal_api_binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ bool EwkInternalApiBinding::Initialize() {
reinterpret_cast<EwkViewJavaScriptPromptReplyFnPtr>(
dlsym(handle_, "ewk_view_javascript_prompt_reply"));

view.MainFrameScrollbarVisibleSet =
reinterpret_cast<EwkViewMainFrameScrollbarVisibleSetFnPtr>(
dlsym(handle_, "ewk_view_main_frame_scrollbar_visible_set"));

// ewk_main
main.SetArguments = reinterpret_cast<EwkSetArgumentsFnPtr>(
dlsym(handle_, "ewk_set_arguments"));
Expand Down Expand Up @@ -105,8 +109,9 @@ bool EwkInternalApiBinding::Initialize() {
view.OnJavaScriptAlert && view.OnJavaScriptConfirm &&
view.OnJavaScriptPrompt && view.JavaScriptAlertReply &&
view.JavaScriptConfirmReply && view.JavaScriptPromptReply &&
main.SetArguments && main.SetVersionPolicy &&
settings.ImePanelEnabledSet && settings.ForceZoomSet &&
console_message.LevelGet && console_message.TextGet &&
console_message.LineGet && console_message.SourceGet;
view.MainFrameScrollbarVisibleSet && main.SetArguments &&
main.SetVersionPolicy && settings.ImePanelEnabledSet &&
settings.ForceZoomSet && console_message.LevelGet &&
console_message.TextGet && console_message.LineGet &&
console_message.SourceGet;
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ typedef Eina_Bool (*Ewk_View_JavaScript_Confirm_Callback)(Evas_Object* o,
typedef Eina_Bool (*Ewk_View_JavaScript_Prompt_Callback)(
Evas_Object* o, const char* message, const char* default_value,
void* user_data);
typedef void (*Ewk_View_Main_Frame_Scrollbar_Visible_Get_Callback)(
Evas_Object* o, Eina_Bool visible, void* user_data);

typedef Eina_Bool (*EwkViewBgColorSetFnPtr)(Evas_Object* obj, int r, int g,
int b, int a);
Expand Down Expand Up @@ -84,6 +86,8 @@ typedef void (*EwkViewJavaScriptConfirmReplyFnPtr)(Evas_Object* o,
Eina_Bool result);
typedef void (*EwkViewJavaScriptPromptReplyFnPtr)(Evas_Object* o,
const char* result);
typedef Eina_Bool (*EwkViewMainFrameScrollbarVisibleSetFnPtr)(
Evas_Object* obj, Eina_Bool enabled);

typedef struct {
EwkViewBgColorSetFnPtr SetBackgroundColor = nullptr;
Expand All @@ -106,7 +110,8 @@ typedef struct {
EwkViewJavaScriptAlertReplyFnPtr JavaScriptAlertReply = nullptr;
EwkViewJavaScriptConfirmReplyFnPtr JavaScriptConfirmReply = nullptr;
EwkViewJavaScriptPromptReplyFnPtr JavaScriptPromptReply = nullptr;

EwkViewMainFrameScrollbarVisibleSetFnPtr MainFrameScrollbarVisibleSet =
nullptr;
} EwkViewProcTable;

typedef void (*EwkSetArgumentsFnPtr)(int argc, char** argv);
Expand Down
14 changes: 14 additions & 0 deletions packages/webview_flutter/tizen/src/webview.cc
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,17 @@ void WebView::HandleWebViewMethodCall(const FlMethodCall& method_call,
} else {
result->Error("Invalid argument", "The argument must be a string.");
}
} else if (method_name == "setVerticalScrollBarEnabled" ||
method_name == "setHorizontalScrollBarEnabled") {
const auto* value = std::get_if<bool>(arguments);
if (value) {
scrollbar_enabled_ = *value;
EwkInternalApiBinding::GetInstance().view.MainFrameScrollbarVisibleSet(
webview_instance_, scrollbar_enabled_);
result->Success();
} else {
result->Error("Invalid argument", "The argument must be a bool.");
}
Comment thread
seungsoo47 marked this conversation as resolved.
} else {
result->NotImplemented();
}
Expand Down Expand Up @@ -773,6 +784,9 @@ void WebView::OnFrameRendered(void* data, Evas_Object* obj, void* event_info) {

void WebView::OnLoadStarted(void* data, Evas_Object* obj, void* event_info) {
WebView* webview = static_cast<WebView*>(data);
EwkInternalApiBinding::GetInstance().view.MainFrameScrollbarVisibleSet(
webview->webview_instance_, webview->scrollbar_enabled_);
Comment on lines +787 to +788
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this API always be called every time the page is reloaded?
You are already calling the set API on line 709.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This API should be called only after the webview is loaded.
After that, the API call on line 709 is intended to immediately reflect the requested state of the UI.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the setting get reset when the page reloads?

If not, I think it would be better to use std:optional<bool> to call the function only when the setting is configured, and to ensure it is not called again once it has already been invoked.

While this code will likely have little impact on performance or behavior, if you want to be clearer, it might be better to treat this as an API constraint and display a warning message if it is called before the page loads.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your review.

When I tried it, the std::optional<bool> variable seems to work correctly only on the first attempt.
In other words, its has_value() function always returns true from the second call onwards.
Therefore, I think it would be better to keep the current code as is.

And this API on the Flutter side can be called while the WebViewController is set up or after it is set up.

Thank you again for your review.


std::string url = std::string(ewk_view_url_get(webview->webview_instance_));
flutter::EncodableMap args = {
{flutter::EncodableValue("url"), flutter::EncodableValue(url)}};
Expand Down
1 change: 1 addition & 0 deletions packages/webview_flutter/tizen/src/webview.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ class WebView : public PlatformView {
std::unique_ptr<BufferPool> tbm_pool_;
bool disposed_ = false;
Ewk_Mouse_Button_Type mouse_button_type_ = (Ewk_Mouse_Button_Type)0;
bool scrollbar_enabled_ = true;
};

#endif // FLUTTER_PLUGIN_WEBVIEW_H_
Loading