Skip to content

Commit 328ccff

Browse files
authored
Merge pull request Sub6Resources#559 from tneotia/feature/web-support
Support for Flutter Web
2 parents ba4c2e1 + 2c52275 commit 328ccff

File tree

11 files changed

+229
-40
lines changed

11 files changed

+229
-40
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//
2+
// Generated file. Do not edit.
3+
//
4+
5+
// ignore_for_file: lines_longer_than_80_chars
6+
7+
import 'package:video_player_web/video_player_web.dart';
8+
import 'package:wakelock_web/wakelock_web.dart';
9+
10+
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
11+
12+
// ignore: public_member_api_docs
13+
void registerPlugins(Registrar registrar) {
14+
VideoPlayerPlugin.registerWith(registrar);
15+
WakelockWeb.registerWith(registrar);
16+
registrar.registerMessageHandler();
17+
}

example/web/favicon.png

917 Bytes
Loading

example/web/icons/Icon-192.png

5.17 KB
Loading

example/web/icons/Icon-512.png

8.06 KB
Loading

example/web/index.html

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<!--
5+
If you are serving your web app in a path other than the root, change the
6+
href value below to reflect the base path you are serving from.
7+
8+
The path provided below has to start and end with a slash "/" in order for
9+
it to work correctly.
10+
11+
Fore more details:
12+
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
13+
-->
14+
<base href="/">
15+
16+
<meta charset="UTF-8">
17+
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
18+
<meta name="description" content="A new Flutter project.">
19+
20+
<!-- iOS meta tags & icons -->
21+
<meta name="apple-mobile-web-app-capable" content="yes">
22+
<meta name="apple-mobile-web-app-status-bar-style" content="black">
23+
<meta name="apple-mobile-web-app-title" content="example">
24+
<link rel="apple-touch-icon" href="icons/Icon-192.png">
25+
26+
<!-- Favicon -->
27+
<link rel="icon" type="image/png" href="favicon.png"/>
28+
29+
<title>example</title>
30+
<link rel="manifest" href="manifest.json">
31+
</head>
32+
<body>
33+
<!-- This script installs service_worker.js to provide PWA functionality to
34+
application. For more information, see:
35+
https://developers.google.com/web/fundamentals/primers/service-workers -->
36+
<script>
37+
if ('serviceWorker' in navigator) {
38+
window.addEventListener('flutter-first-frame', function () {
39+
navigator.serviceWorker.register('flutter_service_worker.js');
40+
});
41+
}
42+
</script>
43+
<script src="main.dart.js" type="application/javascript"></script>
44+
</body>
45+
</html>

example/web/manifest.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "example",
3+
"short_name": "example",
4+
"start_url": ".",
5+
"display": "standalone",
6+
"background_color": "#0175C2",
7+
"theme_color": "#0175C2",
8+
"description": "A new Flutter project.",
9+
"orientation": "portrait-primary",
10+
"prefer_related_applications": false,
11+
"icons": [
12+
{
13+
"src": "icons/Icon-192.png",
14+
"sizes": "192x192",
15+
"type": "image/png"
16+
},
17+
{
18+
"src": "icons/Icon-512.png",
19+
"sizes": "512x512",
20+
"type": "image/png"
21+
}
22+
]
23+
}

lib/src/replaced_element.dart

Lines changed: 3 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ import 'dart:math';
33
import 'package:chewie/chewie.dart';
44
import 'package:chewie_audio/chewie_audio.dart';
55
import 'package:flutter/foundation.dart';
6-
import 'package:flutter/gestures.dart';
76
import 'package:flutter/material.dart';
87
import 'package:flutter/widgets.dart';
98
import 'package:flutter_html/html_parser.dart';
109
import 'package:flutter_html/src/html_elements.dart';
1110
import 'package:flutter_html/src/utils.dart';
11+
import 'package:flutter_html/src/widgets/iframe_unsupported.dart'
12+
if (dart.library.io) 'package:flutter_html/src/widgets/iframe_mobile.dart'
13+
if (dart.library.html) 'package:flutter_html/src/widgets/iframe_web.dart';
1214
import 'package:flutter_html/style.dart';
1315
import 'package:flutter_svg/flutter_svg.dart';
1416
import 'package:html/dom.dart' as dom;
@@ -100,45 +102,6 @@ class ImageContentElement extends ReplacedElement {
100102
}
101103
}
102104

103-
/// [IframeContentElement is a [ReplacedElement] with web content.
104-
class IframeContentElement extends ReplacedElement {
105-
final String src;
106-
final double width;
107-
final double height;
108-
final NavigationDelegate navigationDelegate;
109-
final UniqueKey key = UniqueKey();
110-
111-
IframeContentElement({
112-
String name,
113-
Style style,
114-
this.src,
115-
this.width,
116-
this.height,
117-
dom.Element node,
118-
this.navigationDelegate,
119-
}) : super(name: name, style: style, node: node);
120-
121-
@override
122-
Widget toWidget(RenderContext context) {
123-
final sandboxMode = attributes["sandbox"];
124-
return Container(
125-
width: width ?? (height ?? 150) * 2,
126-
height: height ?? (width ?? 300) / 2,
127-
child: WebView(
128-
initialUrl: src,
129-
key: key,
130-
javascriptMode: sandboxMode == null || sandboxMode == "allow-scripts"
131-
? JavascriptMode.unrestricted
132-
: JavascriptMode.disabled,
133-
navigationDelegate: navigationDelegate,
134-
gestureRecognizers: {
135-
Factory<VerticalDragGestureRecognizer>(() => VerticalDragGestureRecognizer())
136-
},
137-
),
138-
);
139-
}
140-
}
141-
142105
/// [AudioContentElement] is a [ContentElement] with an audio file as its content.
143106
class AudioContentElement extends ReplacedElement {
144107
final List<String> src;

lib/src/utils.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import 'package:flutter/gestures.dart';
22

3+
import 'dart:math';
4+
import 'dart:convert';
5+
36
class Context<T> {
47
T data;
58

@@ -43,3 +46,9 @@ class MultipleTapGestureRecognizer extends TapGestureRecognizer {
4346
}
4447
}
4548
}
49+
50+
String getRandString(int len) {
51+
var random = Random.secure();
52+
var values = List<int>.generate(len, (i) => random.nextInt(255));
53+
return base64UrlEncode(values);
54+
}

lib/src/widgets/iframe_mobile.dart

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import 'package:flutter/foundation.dart';
2+
import 'package:flutter/gestures.dart';
3+
import 'package:flutter/material.dart';
4+
import 'package:flutter_html/html_parser.dart';
5+
import 'package:flutter_html/src/replaced_element.dart';
6+
import 'package:flutter_html/style.dart';
7+
import 'package:webview_flutter/webview_flutter.dart';
8+
import 'package:html/dom.dart' as dom;
9+
10+
/// [IframeContentElement is a [ReplacedElement] with web content.
11+
class IframeContentElement extends ReplacedElement {
12+
final String src;
13+
final double width;
14+
final double height;
15+
final NavigationDelegate navigationDelegate;
16+
final UniqueKey key = UniqueKey();
17+
18+
IframeContentElement({
19+
String name,
20+
Style style,
21+
this.src,
22+
this.width,
23+
this.height,
24+
dom.Element node,
25+
this.navigationDelegate,
26+
}) : super(name: name, style: style, node: node);
27+
28+
@override
29+
Widget toWidget(RenderContext context) {
30+
final sandboxMode = attributes["sandbox"];
31+
return Container(
32+
width: width ?? (height ?? 150) * 2,
33+
height: height ?? (width ?? 300) / 2,
34+
child: WebView(
35+
initialUrl: src,
36+
key: key,
37+
javascriptMode: sandboxMode == null || sandboxMode == "allow-scripts"
38+
? JavascriptMode.unrestricted
39+
: JavascriptMode.disabled,
40+
navigationDelegate: navigationDelegate,
41+
gestureRecognizers: {
42+
Factory<VerticalDragGestureRecognizer>(() => VerticalDragGestureRecognizer())
43+
},
44+
),
45+
);
46+
}
47+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_html/html_parser.dart';
3+
import 'package:flutter_html/src/replaced_element.dart';
4+
import 'package:flutter_html/style.dart';
5+
import 'package:webview_flutter/webview_flutter.dart';
6+
import 'package:html/dom.dart' as dom;
7+
8+
/// [IframeContentElement is a [ReplacedElement] with web content.
9+
class IframeContentElement extends ReplacedElement {
10+
final String src;
11+
final double width;
12+
final double height;
13+
final NavigationDelegate navigationDelegate;
14+
final UniqueKey key = UniqueKey();
15+
16+
IframeContentElement({
17+
String name,
18+
Style style,
19+
this.src,
20+
this.width,
21+
this.height,
22+
dom.Element node,
23+
this.navigationDelegate,
24+
}) : super(name: name, style: style, node: node);
25+
26+
@override
27+
Widget toWidget(RenderContext context) {
28+
return Container(
29+
width: width ?? (height ?? 150) * 2,
30+
height: height ?? (width ?? 300) / 2,
31+
child: Text("Iframes are currently not supported in this environment"),
32+
);
33+
}
34+
}

0 commit comments

Comments
 (0)