Skip to content

Commit 437936f

Browse files
committed
webview code detail
1 parent faaee88 commit 437936f

File tree

10 files changed

+280
-8
lines changed

10 files changed

+280
-8
lines changed

RECORD.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,7 @@ _debugUltimatePreviousSiblingOf
4242
GlobalKey可以记录state,但是需要跟随build创建
4343
https://stackoverflow.com/questions/49862572
4444

45-
readme等view的loading
45+
readme等view的loading
46+
47+
flutter 的跨平台见兼容性意外的话,得益于flutter engine,skia的渲染,只需要canvas
48+
所以第一次运行意外的没有兼容问题,特别是有生之年在ios上看到完全一模一样的下拉刷新

lib/common/style/GSYStyle.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ import 'package:flutter/material.dart';
33
///颜色
44
class GSYColors {
55
static const String primaryValueString = "#24292E";
6+
static const String primaryLightValueString = "#42464b";
7+
static const String primaryDarkValueString = "#121917";
8+
static const String miWhiteString = "#ececec";
9+
static const String actionBlueString = "#267aff";
10+
static const String webDraculaBackgroundColorString = "#282a36";
11+
612
static const int primaryValue = 0xFF24292E;
713
static const int primaryLightValue = 0xFF42464b;
814
static const int primaryDarkValue = 0xFF121917;

lib/common/utils/CommonUtils.dart

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import 'dart:async';
2+
import 'dart:convert';
23

34
import 'package:flutter/material.dart';
5+
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
46
import 'package:gsy_github_app_flutter/common/style/GSYStyle.dart';
57
import 'package:gsy_github_app_flutter/common/utils/NavigatorUtils.dart';
68
import 'package:gsy_github_app_flutter/widget/GSYFlexButton.dart';
@@ -92,11 +94,19 @@ class CommonUtils {
9294
if (pathnames.length == 3) {
9395
NavigatorUtils.goReposDetail(context, userName, repoName);
9496
} else {
95-
//todo web
97+
launchWebView(context, "", url);
9698
}
9799
}
98100
} else {
99-
//todo web
101+
launchWebView(context, "", url);
102+
}
103+
}
104+
105+
static void launchWebView(BuildContext context, String title, String url) {
106+
if (url.startsWith("http")) {
107+
NavigatorUtils.goCodeDetailPageWeb(context, url, title);
108+
} else {
109+
NavigatorUtils.goCodeDetailPageWeb(context, new Uri.dataFromString(url, mimeType: 'text/html', encoding: Encoding.getByName("utf-8")).toString(), title);
100110
}
101111
}
102112

lib/common/utils/EventUtils.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:flutter/material.dart';
2+
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
23
import 'package:gsy_github_app_flutter/common/utils/CommonUtils.dart';
34
import 'package:gsy_github_app_flutter/common/utils/NavigatorUtils.dart';
45

@@ -156,7 +157,8 @@ class EventUtils {
156157
break;
157158
case 'ReleaseEvent':
158159
String url = event["payload"]["release"]["html_url"];
159-
//launchUrl(url);
160+
final flutterWebviewPlugin = new FlutterWebviewPlugin();
161+
flutterWebviewPlugin.launch(url, hidden: true);
160162
break;
161163
case 'IssueCommentEvent':
162164
case 'IssuesEvent':

lib/common/utils/HtmlUtils.dart

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
import 'package:gsy_github_app_flutter/common/style/GSYStyle.dart';
2+
3+
/**
4+
* Created by guoshuyu
5+
* on 2018/7/27.
6+
*/
7+
8+
class HtmlUtils {
9+
static generateCode2HTml(String mdData, {String backgroundColor = GSYColors.miWhiteString, String lang = 'java', userBR = true}) {
10+
String currentData = (mdData != null && mdData.indexOf("<code>") == -1)
11+
? "<body>\n" + "<pre class=\"pre\">\n" + "<code lang='$lang'>\n" + mdData + "</code>\n" + "</pre>\n" + "</body>\n"
12+
: "<body>\n" + "<pre class=\"pre\">\n" + mdData + "</pre>\n" + "</body>\n";
13+
return generateHtml(currentData, backgroundColor: backgroundColor, userBR: userBR);
14+
}
15+
16+
static generateHtml(String mdData, {String backgroundColor = GSYColors.webDraculaBackgroundColorString, userBR = true}) {
17+
if (mdData == null) {
18+
return "";
19+
}
20+
RegExp exp = new RegExp("<code(([\s\S])*?)<\/code>");
21+
Iterable<Match> tags = exp.allMatches(mdData);
22+
String mdDataCode = mdData;
23+
for (Match m in tags) {
24+
String match = m.group(0).replaceAll(new RegExp("\n"), "\n\r<br>");
25+
mdDataCode = mdDataCode.replaceAll(m.group(0), match);
26+
}
27+
28+
exp = new RegExp("<pre(([\s\S])*?)<\/pre>");
29+
tags = exp.allMatches(mdDataCode);
30+
for (Match m in tags) {
31+
if (m.group(0).indexOf("<code>") < 0) {
32+
String match = m.group(0).replaceAll(new RegExp("\n"), "\n\r<br>");
33+
mdDataCode = mdDataCode.replaceAll(m.group(0), match);
34+
}
35+
}
36+
37+
exp = new RegExp("<pre>(([\s\S])*?)<\/pre>");
38+
tags = exp.allMatches(mdDataCode);
39+
for (Match m in tags) {
40+
if (m.group(0).indexOf("<code>") < 0) {
41+
String match = m.group(0).replaceAll(new RegExp("\n"), "\n\r<br>");
42+
mdDataCode = mdDataCode.replaceAll(m.group(0), match);
43+
}
44+
}
45+
46+
exp = new RegExp("href=\"(.*?)\"");
47+
tags = exp.allMatches(mdDataCode);
48+
for (Match m in tags) {
49+
String capture = m.group(0);
50+
if (capture.indexOf("http://") < 0 && capture.indexOf("https://") < 0 && capture.indexOf("#") != 0) {
51+
mdDataCode = mdDataCode.replaceAll(m.group(0), "gsygithub://" + capture);
52+
}
53+
}
54+
55+
return generateCodeHtml(mdDataCode, false, backgroundColor: backgroundColor, actionColor: GSYColors.actionBlueString, userBR: userBR);
56+
}
57+
58+
/**
59+
* style for mdHTml
60+
*/
61+
static generateCodeHtml(mdHTML, wrap, {backgroundColor = GSYColors.white, String actionColor = GSYColors.actionBlueString, userBR = true}) {
62+
return "<html>\n" +
63+
"<head>\n" +
64+
"<meta charset=\"utf-8\" />\n" +
65+
"<title></title>\n" +
66+
"<meta name=\"viewport\" content=\"width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;\"/>" +
67+
"<link href=\"https:\/\/cdn.bootcss.com/highlight.js/9.12.0/styles/dracula.min.css\" rel=\"stylesheet\">\n" +
68+
"<script src=\"https:\/\/cdn.bootcss.com/highlight.js/9.12.0/highlight.min.js\"></script> " +
69+
"<script>hljs.configure({'useBR': " +
70+
userBR.toString() +
71+
"});hljs.initHighlightingOnLoad();</script> " +
72+
"<style>" +
73+
"body{background: " +
74+
backgroundColor +
75+
";}" +
76+
"a {color:" +
77+
actionColor +
78+
" !important;}" +
79+
".highlight pre, pre {" +
80+
" word-wrap: " +
81+
(wrap ? "break-word" : "normal") +
82+
"; " +
83+
" white-space: " +
84+
(wrap ? "pre-wrap" : "pre") +
85+
"; " +
86+
"}" +
87+
"thead, tr {" +
88+
"background:" +
89+
GSYColors.miWhiteString +
90+
";}" +
91+
"td, th {" +
92+
"padding: 5px 10px;" +
93+
"font-size: 12px;" +
94+
"direction:hor" +
95+
"}" +
96+
".highlight {overflow: scroll; background: " +
97+
GSYColors.miWhiteString +
98+
"}" +
99+
"tr:nth-child(even) {" +
100+
"background:" +
101+
GSYColors.primaryLightValueString +
102+
";" +
103+
"color:" +
104+
GSYColors.miWhiteString +
105+
";" +
106+
"}" +
107+
"tr:nth-child(odd) {" +
108+
"background: " +
109+
GSYColors.miWhiteString +
110+
";" +
111+
"color:" +
112+
GSYColors.primaryLightValueString +
113+
";" +
114+
"}" +
115+
"th {" +
116+
"font-size: 14px;" +
117+
"color:" +
118+
GSYColors.miWhiteString +
119+
";" +
120+
"background:" +
121+
GSYColors.primaryLightValueString +
122+
";" +
123+
"}" +
124+
"</style>" +
125+
"</head>\n" +
126+
"<body>\n" +
127+
mdHTML +
128+
"</body>\n" +
129+
"</html>";
130+
}
131+
132+
static parseDiffSource(String diffSource, bool wrap) {
133+
if (diffSource == null) {
134+
return "";
135+
}
136+
List<String> lines = diffSource.split("\n");
137+
String source = "";
138+
int addStartLine = -1;
139+
int removeStartLine = -1;
140+
int addLineNum = 0;
141+
int removeLineNum = 0;
142+
int normalLineNum = 0;
143+
for (int i = 0; i < lines.length; i++) {
144+
String line = lines[i];
145+
String lineNumberStr = "";
146+
String classStr = "";
147+
int curAddNumber = -1;
148+
int curRemoveNumber = -1;
149+
150+
if (line.indexOf("+") == 0) {
151+
classStr = "class=\"hljs-addition\";";
152+
curAddNumber = addStartLine + normalLineNum + addLineNum;
153+
addLineNum++;
154+
} else if (line.indexOf("-") == 0) {
155+
classStr = "class=\"hljs-deletion\";";
156+
curRemoveNumber = removeStartLine + normalLineNum + removeLineNum;
157+
removeLineNum++;
158+
} else if (line.indexOf("@@") == 0) {
159+
classStr = "class=\"hljs-literal\";";
160+
removeStartLine = getRemoveStartLine(line);
161+
addStartLine = getAddStartLine(line);
162+
addLineNum = 0;
163+
removeLineNum = 0;
164+
normalLineNum = 0;
165+
} else if (!(line.indexOf("\\") == 0)) {
166+
curAddNumber = addStartLine + normalLineNum + addLineNum;
167+
curRemoveNumber = removeStartLine + normalLineNum + removeLineNum;
168+
normalLineNum++;
169+
}
170+
lineNumberStr =
171+
getDiffLineNumber(curRemoveNumber == -1 ? "" : (curRemoveNumber.toString() + ""), curAddNumber == -1 ? "" : (curAddNumber.toString() + ""));
172+
source = source + "\n" + "<div " + classStr + ">" + (wrap ? "" : lineNumberStr + getBlank(1)) + line + "</div>";
173+
}
174+
return source;
175+
}
176+
177+
static getRemoveStartLine(line) {
178+
try {
179+
return int.parse(line.substring(line.indexOf("-") + 1, line.indexOf(",")));
180+
} catch (e) {
181+
return 1;
182+
}
183+
}
184+
185+
static getAddStartLine(line) {
186+
try {
187+
return int.parse(line.substring(line.indexOf("+") + 1, line.indexOf(",", line.indexOf("+"))));
188+
} catch (e) {
189+
return 1;
190+
}
191+
}
192+
193+
static getDiffLineNumber(String removeNumber, String addNumber) {
194+
int minLength = 4;
195+
return getBlank(minLength - removeNumber.length) + removeNumber + getBlank(1) + getBlank(minLength - addNumber.length) + addNumber;
196+
}
197+
198+
static getBlank(num) {
199+
String builder = "";
200+
for (int i = 0; i < num; i++) {
201+
builder += " ";
202+
}
203+
return builder;
204+
}
205+
}

lib/common/utils/NavigatorUtils.dart

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:async';
22

33
import 'package:flutter/material.dart';
44
import 'package:gsy_github_app_flutter/page/CodeDetailPage.dart';
5+
import 'package:gsy_github_app_flutter/page/CodeDetailPageWeb.dart';
56
import 'package:gsy_github_app_flutter/page/CommonListPage.dart';
67
import 'package:gsy_github_app_flutter/page/HomePage.dart';
78
import 'package:gsy_github_app_flutter/page/IssueDetailPage.dart';
@@ -76,8 +77,7 @@ class NavigatorUtils {
7677
}
7778

7879
///文件代码详情
79-
static gotoCodeDetailPage(BuildContext context,
80-
{String title, String userName, String reposName, String path, String data, String branch, String htmlUrl}) {
80+
static gotoCodeDetailPage(BuildContext context, {String title, String userName, String reposName, String path, String data, String branch, String htmlUrl}) {
8181
Navigator.push(
8282
context,
8383
new MaterialPageRoute(
@@ -114,4 +114,13 @@ class NavigatorUtils {
114114
needHomeIcon: needHomeIcon,
115115
)));
116116
}
117+
118+
static Future<Null> goCodeDetailPageWeb(BuildContext context, String url, String title) {
119+
return Navigator.push(
120+
context,
121+
new MaterialPageRoute(
122+
builder: (context) => new CodeDetailPageWeb(url, title),
123+
),
124+
);
125+
}
117126
}

lib/page/CodeDetailPageWeb.dart

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import 'package:flutter/cupertino.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
4+
5+
/**
6+
* webview版本
7+
* Created by guoshuyu
8+
* on 2018/7/27.
9+
*/
10+
class CodeDetailPageWeb extends StatelessWidget {
11+
final String url;
12+
final String title;
13+
14+
CodeDetailPageWeb(this.url, this.title);
15+
16+
@override
17+
Widget build(BuildContext context) {
18+
return new WebviewScaffold(
19+
url: url,
20+
withLocalUrl: true,
21+
appBar: new AppBar(
22+
title: new Text(title),
23+
),
24+
);
25+
}
26+
}

lib/page/PushDetailPage.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import 'package:flutter/material.dart';
44
import 'package:gsy_github_app_flutter/common/dao/ReposDao.dart';
55
import 'package:gsy_github_app_flutter/common/net/Address.dart';
66
import 'package:gsy_github_app_flutter/common/style/GSYStyle.dart';
7+
import 'package:gsy_github_app_flutter/common/utils/CommonUtils.dart';
78
import 'package:gsy_github_app_flutter/common/utils/NavigatorUtils.dart';
89
import 'package:gsy_github_app_flutter/widget/GSYCommonOptionWidget.dart';
910
import 'package:gsy_github_app_flutter/widget/GSYListState.dart';
1011
import 'package:gsy_github_app_flutter/widget/GSYPullLoadWidget.dart';
1112
import 'package:gsy_github_app_flutter/widget/GSYTitleBar.dart';
1213
import 'package:gsy_github_app_flutter/widget/PushCoedItem.dart';
1314
import 'package:gsy_github_app_flutter/widget/PushHeader.dart';
15+
import 'package:gsy_github_app_flutter/common/utils/HtmlUtils.dart';
1416

1517
/**
1618
* Created by guoshuyu
@@ -74,8 +76,9 @@ class _PushDetailPageState extends GSYListState<PushDetailPage> {
7476
}
7577
PushCodeItemViewModel itemViewModel = pullLoadWidgetControl.dataList[index - 1];
7678
return new PushCodeItem(itemViewModel, () {
77-
NavigatorUtils.gotoCodeDetailPage(context, title: itemViewModel.name, userName: userName, reposName: reposName, data: itemViewModel.patch,
78-
htmlUrl: itemViewModel.blob_url,);
79+
String html =
80+
HtmlUtils.generateCode2HTml(HtmlUtils.parseDiffSource(itemViewModel.patch, false), backgroundColor: GSYColors.webDraculaBackgroundColorString, lang: '', userBR: false);
81+
CommonUtils.launchWebView(context, itemViewModel.name, html);
7982
});
8083
}
8184

pubspec.lock

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,13 @@ packages:
200200
description: flutter
201201
source: sdk
202202
version: "0.0.0"
203+
flutter_webview_plugin:
204+
dependency: "direct main"
205+
description:
206+
name: flutter_webview_plugin
207+
url: "https://pub.flutter-io.cn"
208+
source: hosted
209+
version: "0.1.6"
203210
fluttertoast:
204211
dependency: "direct main"
205212
description:

pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ dependencies:
2020
share: ^0.5.2
2121
flutter_spinkit: ^2.0.0
2222
get_version: ^0.0.5
23+
flutter_webview_plugin: ^0.1.6
2324

2425
dev_dependencies:
2526
build_runner: ^0.7.6

0 commit comments

Comments
 (0)