merge master

This commit is contained in:
xiaojia.dxj
2019-10-30 10:31:36 +08:00
216 changed files with 12147 additions and 1529 deletions

26
.github/ISSUE_TEMPLATE/bug-report.md vendored Normal file
View File

@ -0,0 +1,26 @@
---
name: "\U0001F41B Bug Report"
about: Something isn't working as expected
---
## Bug Report
**仅限中文与英文**, 其他语言的提交将直接被关闭
请先确认查找了已有的 issue [GitHub issues](https://github.com/apache/incubator-shardingsphere-example/issues).
为了更好的收录您反馈或者提交的相关pr. 请您关注您提交的问题, 我们可能需要更多的详细信息, 我们会在issue下先您收集相关信息,
如果长时间未得到您的回复, 如果我们无法在某些环境上重现该问题, 并且您**超过7天未回复**, 我们可能会关 **闭掉issue**, 谢谢
### 您当前的flutter doctor信息
### 预期的表现
### 实际的表现
### 预期的分析 (给出您能想到, 任何您能想到的)
### 重现的方式, 例如从 A界面 点击 b, 跳转到B页面, 界面出现溢出乱码等.
### 用于重现此问题或者可能解决以上问题的示例代码例如github 链接代码)

View File

@ -0,0 +1,18 @@
---
name: "\U0001F680 Feature Request"
about: I have a suggestion
---
## Feature Request
**仅限中文与英文**, 其他语言的提交将直接被关闭
请先确认查找了已有的 issue [GitHub issues](https://github.com/apache/incubator-shardingsphere-example/issues).
为了更好的收录您反馈或者提交的相关pr. 请您关注您提交的问题, 我们可能需要更多的详细信息, 我们会在issue下先您收集相关信息,
如果长时间未得到您的回复, 如果我们无法在某些环境上重现该问题, 并且您**超过7天未回复**, 我们可能会关 **闭掉issue**, 谢谢
### 您的功能需求是否与哪些问题有关?
### 描述您想要的功能.

62
.github/ISSUE_TEMPLATE/page-about.md vendored Normal file
View File

@ -0,0 +1,62 @@
---
name: "📄 Page About"
about: something about page
---
## Page About
**仅限中文与英文**, 其他语言的提交将直接被关闭
请先确认查找了已有的 issue [GitHub issues](https://github.com/apache/incubator-shardingsphere-example/issues).
为了更好的收录您反馈或者提交的相关pr. 请您关注您提交的问题, 我们可能需要更多的详细信息, 我们会在issue下先您收集相关信息,
如果长时间未得到您的回复, 如果我们无法在某些环境上重现该问题, 并且您**超过7天未回复**, 我们可能会关 **闭掉issue**, 谢谢
## 界面增加或者更新的内容概括
## 界面数据
例如:
```
{
"name": "standard_for_slider",
"screenShot": "",
"author":"sanfan",
"title":"slider组件",
"email": "hanxu@qq.com",
"desc": "slider, new Slider",
"id": "8ab2b5c2_42ae_4241_9c8a_5c9e1f92b096"
}
```
## Page 关联的 DEMO 信息
例如:
```
{
"name": "intor page",
"screenShot": "",
"author":"sanfan",
"title":"介绍页",
"email": "hanxu317@qq.com",
"desc": "desc",
"id": "ee4feb8e_32ae_4241_9c8a_5c9e1f92b096"
},
{
"name": "intor pag2e",
"screenShot": "",
"author":"sanfan",
"title":"介绍页",
"email": "hanxu317@qq.com",
"desc": "desc",
"id": "ee4feb8e_32ae_4241_9c8a_5c9e1f92b097"
}
```
## 引入第三方包的文件与版本号(如果有引入, 请标明)

14
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View File

@ -0,0 +1,14 @@
---
name: "\U0001F914 Question"
about: Usage question that isn't answered in docs or discussion
---
## Question
**仅限中文与英文**, 其他语言的提交将直接被关闭
请先确认查找了已有的 issue [GitHub issues](https://github.com/apache/incubator-shardingsphere-example/issues).
为了更好的收录您反馈或者提交的相关pr. 请您关注您提交的问题, 我们可能需要更多的详细信息, 我们会在issue下先您收集相关信息,
如果长时间未得到您的回复, 如果我们无法在某些环境上重现该问题, 并且您**超过7天未回复**, 我们可能会关 **闭掉issue**, 谢谢

View File

View File

@ -0,0 +1,19 @@
#### What does this PR do?
[TrelloCard/Issue/Story](LINK_TO_STORY)
##### Why are we doing this? Any context or related work?
#### Where should a reviewer start?
#### Manual testing steps?
#### Screenshots
---
#### Database changes
#### Deployment instructions
#### New ENV variables

6
.gitignore vendored
View File

@ -18,6 +18,7 @@
.metadata
# IntelliJ related
*.ipr
@ -33,9 +34,14 @@
.flutter-plugins
.packages
.pub-cache/
pubspec.lock
.pub/
/build/
# goCli related
go-cli/.packages
go-cli/pubspec.lock
# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle

View File

@ -1,86 +1,358 @@
## 更新日志
#### 8/28/2019
- [x] Modify: IsOpen 的移步判断
- [x] Update index.md
- [x] Update index.dart
#### 5/28/2019
- [x] change:async master
- [x] modfiy:应用商店
- [x] Merge pull request #222 from DeckeDeng/develop
- [x] add home scaffold
#### 8/22/2019
- [x] Merge pull request #322 from alibaba/beta
- [x] Modify: web view 方法回退
- [x] Merge pull request #321 from alibaba/beta
- [x] Merge pull request #317 from alibaba/beta
- [x] Merge branch 'master' into beta
- [x] Update contribute.md
#### 8/12/2019
- [x] update: doc & tpl
- [x] Update tpl.md
- [x] Merge pull request #313 from Nealyang/beta
- [x] 添加登陆错误提醒
#### 3/11/2019
- [x] Update README-en.md
#### 8/15/2019
- [x] update: router path
- [x] ci
- [x] update: view remote code
- [x] 整理文件
#### 8/13/2019
- [x] Modify
- [x] Modfiy:
- [x] update: page issue template
#### 8/1/2019
- [x] merge code
#### 7/29/2019
- [x] Merge branch 'master' of github.com:alibaba/flutter-go into beta
- [x] delete .github no use file
- [x] docs(update: pr template):
- [x] del: no use file
- [x] Merge branch 'master' of github.com:alibaba/flutter-go
- [x] docs(add widget about issue):
- [x] Merge branch 'temp' into beta
- [x] 迁移位置
- [x] update: template
- [x] update: 处理合并导致的总理2
#### 8/7/2019
- [x] fix bug
- [x] Merge pull request #302 from Nealyang/beta
- [x] remove get collection
- [x] tep
- [x] update: 完成markdown动态更新
#### 8/8/2019
- [x] remove user appBar
- [x] bottomBar 添加个人中心
- [x] Merge pull request #309 from DeckeDeng/beta2
- [x] ios project.pbxproj
- [x] Merge pull request #308 from DeckeDeng/beta2
- [x] Merge pull request #304 from Nealyang/beta
- [x] 修改 ios 配置文件
- [x] update: 临时增加code-review页
#### 6/28/2019
- [x] Merge pull request #264 from DeckeDeng/beta2
- [x] Merge pull request #263 from DeckeDeng/beta2
- [x] Merge branch 'beta' into beta2
- [x] 消息反馈页面
#### 2/1/2019
- [x] Merge branch 'develop' of https://github.com/alibaba/flutter-go into develop
- [x] feat:android splash
- [x] feat:add android splash
- [x] Merge pull request #116 from hanxu317317/develop
- [x] docs(更新Readme中环境信息):
- [x] Merge pull request #115 from hanxu317317/develop
- [x] feat(首页欢迎图, 加入第一次访问判断.):
- [x] Merge branch 'develop' into sptil
- [x] update: ios启动图描述
- [x] fix:yaml
- [x] fix:
- [x] Merge pull request #113 from hanxu317317/develop
- [x] fix:mtl buidl apk test
- [x] refactor(conflict):
- [x] add sp
- [x] fix(解决由于flutter 版本问题导致的报错):
- [x] fix:back
- [x] fix:package err
- [x] fix:modify github package name fail and test
- [x] fix:build before modify package's name
#### 7/12/2019
- [x] Merge pull request #279 from Nealyang/beta
- [x] add
- [x] d
#### 8/6/2019
- [x] issuse message
- [x] Merge pull request #294 from Nealyang/beta
- [x] 修改为线上地址
- [x] 个人中心、收藏、搜索
#### 7/25/2019
- [x] Merge branch 'beta' of github.com:alibaba/flutter-go
#### 7/23/2019
- [x] zefyr
#### 7/22/2019
- [x] feature:个人设置
#### 7/15/2019
- [x] appstore 反馈错误
- [x] readme错误
- [x] 标题错误,跳转错误
#### 7/11/2019
- [x] update: 迁移新老数据结构与收藏
- [x] update: 增加环境配置. 挂载在application静态属性上
- [x] update: 修改文章
#### 4/8/2019
- [x] flutter project switch ios or android by androidstudio
- [x] android permission
- [x] remove extra files
#### 6/18/2019
- [x] 推送ios/android,test
#### 6/15/2019
- [x] 删除node相关
- [x] Merge branch 'develop' of github.com:alibaba/flutter-common-widgets-app into web
- [x] update: 完善demo
- [x] update: 界面增加title属性
- [x] add: cli使用说明
#### 6/11/2019
- [x] update: 替换markdown包引入方式
- [x] add: 加入标准page模板
- [x] 加入标准page
- [x] 加入初始化demo
- [x] 引入三方flutter_markdown gi
#### 6/10/2019
- [x] Merge pull request #249 from Nealyang/beta
- [x] 添加收藏功能
- [x] update: 标准化代码.
- [x] goCli 完成90%
#### 6/4/2019
- [x] markdown
- [x] 加入初始gocli
- [x] add page demo
- [x] 增加page的统一入口
- [x] add demos packges
- [x] Merge pull request #240 from Nealyang/beta
- [x] 退出登陆、feedback 测试
#### 5/31/2019
- [x] 添加个人中心
#### 5/30/2019
- [x] 首页不刷新
- [x] Merge pull request #1 from forever-713/zuston-patch-1
- [x] Fix App name error
#### 5/29/2019
- [x] 添加 github oAuth 认证,添加错误提醒
#### 5/23/2019
- [x] readme.md
- [x] Merge pull request #219 from weikx/develop
- [x] Merge pull request #215 from DeckeDeng/develop
- [x] delete firstPage
- [x] de
- [x] Test测试分支
- [x] Merge branch 'develop' of https://github.com/weikx/flutter-go into develop
- [x] Change word 'Free' into 'Three'
- [x] Chang word 'Free' into 'Three'
#### 5/17/2019
- [x] Merge pull request #216 from alibaba/master
#### 5/14/2019
- [x] update version
#### 2/3/2019
- [x] fix(解决ios报错):
- [x] Merge pull request #119 from Nealyang/master
- [x] fix:fix code conflic
- [x] fix: code conflict
- [x] Merge branch 'develop' into master
- [x] fix:view code
- [x] Merge pull request #118 from alibaba/dev/yisheng
#### 5/9/2019
- [x] test version
#### 5/7/2019
- [x] merge origin
- [x] add update test
- [x] Merge branch 'develop' of github.com:alibaba/flutter-go
- [x] cookie 校验
- [x] modify home.dart bottom tab
- [x] session 验证
- [x] merge develop
- [x] 登陆
- [x] Merge pull request #205 from alibaba/dev/sanl
- [x] modify bottom tab
- [x] delete ios file
- [x] add apk
- [x] Login 登陆界面
#### 5/6/2019
- [x] add login
#### 5/1/2019
- [x] Modfiy 改造业内资讯页面
#### 4/30/2019
- [x] Add:二期开发-重构首页布局
- [x] gradle 4.10.2 包添加AndroidX配置
#### 2/19/2019
- [x] packagename
- [x] Merge pull request #148 from alibaba/dev/yisheng
- [x] refactor:按照代码规范调整import 文件
- [x] update: 规范
- [x] Merge pull request #147 from Nealyang/master
- [x] fix:修复TabBar demo
- [x] Merge pull request #146 from Nealyang/master
- [x] refactor: 根据规范重构代码
- [x] Merge pull request #145 from alibaba/dev/yisheng
- [x] refactor:按照代码规范调整markdow解析
- [x] refactor(规范化代码):
- [x] Merge pull request #143 from Nealyang/master
- [x] refactor:按规范修改代码、注释等
- [x] Merge pull request #142 from Nealyang/master
- [x] commit
- [x] Merge pull request #141 from Nealyang/master
- [x] Merge pull request #140 from Nealyang/master
- [x] Merge pull request #135 from hanxu317317/develop
- [x] Merge branch 'develop' into develop
- [x] Merge pull request #139 from Nealyang/master
- [x] Merge branch 'develop' of github.com:alibaba/flutter-common-widgets-app
- [x] refactor:根据规范,重构代码
- [x] modify code comments
- [x] Merge pull request #138 from alibaba/dev/yisheng
- [x] refactor:按照代码规范调整注释文件
#### 4/29/2019
- [x] test app store
- [x] Merge branch 'master' into dev/sanl
- [x] 修改bug
#### 4/26/2019
- [x] Debug: GoogleService-Info.plist 位置问题 导致错误
- [x] change LICENSE date
- [x] 变更许可
- [x] Merge pull request #189 from alibaba/develop
- [x] change License
#### 4/22/2019
- [x] release apk
- [x] Merge pull request #192 from alibaba/dev/yisheng
- [x] 格式化
- [x] Merge pull request #191 from alibaba/dev/yisheng
- [x] Delete:删除 .gradle 文件夹
- [x] Merge pull request #188 from alibaba/dev/yisheng
#### 4/17/2019
- [x] gridView 网格效果 图片流
- [x] 添加渐变效果/网络图片覆盖图层渲染/图片填充
#### 1/31/2019
- [x] Merge pull request #112 from alibaba/dev/yisheng
- [x] Debug:canvas 路由问题
- [x] Merge pull request #111 from alibaba/dev/yisheng
- [x] feat: Canvas 细化各种方法
- [x] add file
- [x] fix:code
- [x] feat(加入启动图, 时间2秒):
#### 4/12/2019
- [x] update: 修改错字
- [x] Merge pull request #180 from alibaba/develop
- [x] add: doc roadmap
#### 4/1/2019
- [x] remove recruit
- [x] move recruit
#### 3/31/2019
- [x] 增加模板
- [x] Create pull_request_template.md
- [x] Delete .github
- [x] Create .github
- [x] Merge pull request #173 from alibaba/master
#### 2/2/2019
- [x] fix: 部分代码添加 mounted
- [x] Merge pull request #117 from alibaba/dev/yisheng
- [x] fix:修复Canvas组件收藏的bug
#### 2/20/2019
- [x] 同步文件
- [x] Merge pull request #152 from hanxu317317/develop
- [x] 更新跳转页方式
- [x] modify logo
- [x] Merge pull request #149 from hanxu317317/develop
- [x] fix(解决返回首页报错的问题):
#### 2/11/2019
- [x] fix: 部分代码 analysis 解决
#### 2019-2-5
- [x] 处理因为flutter版本导致的项目运行不起来
- [x] 更新readme, 加入开发日志, 与相关说明
- [x] 加入 首页欢迎效果图
- [x] refactor(整理richText的说明):
- [x] 解决一些页面的code演示打不开的问题
- [x] add:开发规范
- [x] add:版本更新历史链接
- [x] Update README.md
- [x] add:添加版本号
- [x] feat:添加代码开发规范
- [x] refactor(update: version & fiexed warns):
- [x] fix(solve conflict):
- [x] modify:toast and andrid apk label
- [x] Add:自动 pr 工具抓取器,抓取两周前至今的,提交数据,并去重
- [x] fix:fluttetToast backHome
- [x] fix:modified the style of toast && remote files
- [x] chore(删除tools/log.json):
- [x] 重构文件结构
- [x] 关于手册图标更换
- [x] 增加demo: CupertinoNavigationBar CupertinoPageRoute CupertinoPageScaffold CupertinoPickerCupertinoPopupSurface CupertinoTimerPickerDemo
- [x] 处理因为flutter版本导致的项目运行不起来
- [x] 更新readme, 加入开发日志, 与相关说明
- [x] 加入 首页欢迎效果图
- [x] refactor(整理richText的说明):
- [x] 解决一些页面的code演示打不开的问题
- [x] add:开发规范
- [x] add:版本更新历史链接
- [x] Update README.md
- [x] add:添加版本号
- [x] feat:添加代码开发规范
- [x] refactor(update: version & fiexed warns):
- [x] fix(solve conflict):
- [x] modify:toast and andrid apk label
- [x] Add:自动 pr 工具抓取器,抓取两周前至今的,提交数据,并去重
- [x] fix:fluttetToast backHome
- [x] fix:modified the style of toast && remote files
- [x] chore(删除tools/log.json):
- [x] 重构文件结构
- [x] 关于手册图标更换
- [x] 增加demo: CupertinoNavigationBar CupertinoPageRoute CupertinoPageScaffold CupertinoPickerCupertinoPopupSurface CupertinoTimerPickerDemo
#### 2019-1-24
- [x] 功能:更新小部件的图标
- [x] 功能添加CupertinoTimerPickerDemo
- [x] 调试:消除警告
- [x] 修复:关于手册图标更换
- [x] 添加:文案描述
- [x] 添加CupertinoPickerCupertinoPopupSurface
- [x] 功能:更新小部件的图标
- [x] 功能添加CupertinoTimerPickerDemo
- [x] 调试:消除警告
- [x] 修复:关于手册图标更换
- [x] 添加:文案描述
- [x] 添加CupertinoPickerCupertinoPopupSurface
#### 2019-1-23
- [x] 修复: 导航栏home返回报错
- [x] 修复:收集错误
- [x] 添加CupertinoNavigationBar CupertinoPageRoute CupertinoPageScaffold
- [x] 修复: 导航栏home返回报错
- [x] 修复:收集错误
- [x] 添加CupertinoNavigationBar CupertinoPageRoute CupertinoPageScaffold
#### 2019-1-22
- [x] 功能在Allsimon拉请求中添加英文简介
- [x] 功能在Allsimon拉请求中添加英文简介
#### 2019-1-21
- [x] 功能Cupertino的子项
- [x] 功能Cupertino的子项
#### 2019-1-20
- [x] 功能CupertinoSwitch演示
- [x] 功能:为搜索列表加入图标
- [x] 功能CupertinoSliverRefreshControl演示
- [x] 功能CupertinoSliverNavigationBar演示
- [x] 功能CupertinoSwitch演示
- [x] 功能:为搜索列表加入图标
- [x] 功能CupertinoSliverRefreshControl演示
- [x] 功能CupertinoSliverNavigationBar演示
#### 2019-1-18
- [x] 更新SharedPreferences保存数据和android设备布局溢出
- [x] 功能添加CupertinoScrollbar演示
- [x] 功能:第四页暂时用欢迎页替代。后期再开发
- [x] 更新SharedPreferences保存数据和android设备布局溢出
- [x] 功能添加CupertinoScrollbar演示
- [x] 功能:第四页暂时用欢迎页替代。后期再开发
#### 2019-1-17
- [x] 添加:+许可证
- [x] 添加:+许可证
#### 2019-1-16
- [x] 转换将README翻译为En语言环境
- [x] 功能CupertinoScrollbar演示
- [x] 转换将README翻译为En语言环境
- [x] 功能CupertinoScrollbar演示
#### 2019-1-14
- [x] 添加:增加手册页面
- [x] 功能:文字演示
- [x] 重构:修改过的图标
- [x] 重构文档文章组件收藏新增webView
- [x] 重构:修改过的演示
- [x] 重构:代码视图
- [x] 更新:版本 和readme.md
- [x] 修改:添加代码视图
- [x] 功能:添加搜索历史记录板
- [x] 修改:列出加标头错误
- [x] 添加:增加手册页面
- [x] 功能:文字演示
- [x] 重构:修改过的图标
- [x] 重构文档文章组件收藏新增webView
- [x] 重构:修改过的演示
- [x] 重构:代码视图
- [x] 更新:版本 和readme.md
- [x] 修改:添加代码视图
- [x] 功能:添加搜索历史记录板
- [x] 修改:列出加标头错误
#### 2019-1-15
- [x] 功能welcomepage
- [x] 功能welcomepage
#### 2019-1-13
- [x] 添加:一些输入描述
- [x] 功能加入GridPaperSliverGrid
- [x] 重构修改db
- [x] 重构:删除数据库 TabBarView
- [x] 添加:网格视图
- [x] 修改checkbosListTile 错误
- [x] 修改:自动提示文案
- [x] 功能:增加免责声明,声明组件,自动弹出,左上角入口
- [x] 重构整理数据库初始逻辑判断数据库完整性判断是否存在已知的catwidgetcollection 三张表。
- [x] 修复DialogDemo无法关闭的问题
- [x] 添加:一些输入描述
- [x] 功能加入GridPaperSliverGrid
- [x] 重构修改db
- [x] 重构:删除数据库 TabBarView
- [x] 添加:网格视图
- [x] 修改checkbosListTile 错误
- [x] 修改:自动提示文案
- [x] 功能:增加免责声明,声明组件,自动弹出,左上角入口
- [x] 重构整理数据库初始逻辑判断数据库完整性判断是否存在已知的catwidgetcollection 三张表。
- [x] 修复DialogDemo无法关闭的问题
#### 2019-1-12
- [x] 修复icon没有但内容有的组件给补充了icon
- [x] 修改1.整理文件 2.修正分析
- [x] 更新flutter_rookie_book => flutter_go
- [x] 更新更新SearchInput文件名=> search_input
- [x] 修改:文件名称的大小写规范
- [x] 修改修正bottomNavigationBar iconButton警告
- [x] 修复icon没有但内容有的组件给补充了icon
- [x] 修改1.整理文件 2.修正分析
- [x] 更新flutter_rookie_book => flutter_go
- [x] 更新更新SearchInput文件名=> search_input
- [x] 修改:文件名称的大小写规范
- [x] 修改修正bottomNavigationBar iconButton警告

76
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at zhu.yan@alibaba-inc.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

1
CONTRIBUTING.md Normal file
View File

@ -0,0 +1 @@
[Flutter Go 共建](https://github.com/alibaba/flutter-go/blob/master/docs/contribute.md)

Binary file not shown.

View File

@ -1,28 +1,105 @@
## Flutter Go
# Flutter Go
[中文简体](https://github.com/alibaba/flutter-go/blob/master/README.md) | Language: [English](https://github.com/alibaba/flutter-go/blob/master/README-en.md)
![https://img.alicdn.com/tfs/TB1OJkeHNYaK1RjSZFnXXa80pXa-229-229.png](https://img.alicdn.com/tfs/TB1OJkeHNYaK1RjSZFnXXa80pXa-229-229.png)
> Help developers get started quickly Flutter **Flutter Go 1.0 Android has been released**
> Help developers get started quickly Flutter
## News
### 🔥 `Flutter Go 2.0` released
> Flutter Go 2.0 according to [The Flutter-Go Roadmap for 2019](https://github.com/alibaba/flutter-go#the-flutter-go-roadmap%E8%B7%AF%E7%BA%BF%E5%9B%BE-for-2019) beginning of the year, the new feature is:
## Download URL
<h6>mark✔ is this version</h6>
Android download URL:
- [x] [ `Flutter Go` website ](https://flutter-go.pub/website/) (newspublishlearn)
- [x] [ `Flutter Go web` ](https://github.com/alibaba/flutter-go/tree/web/flutter-go-web-0.0.1) (web version to learn)
- [online preview ](https://flutter-go.pub/flutter_go_web/)
- [resource ](https://github.com/alibaba/flutter-go/tree/web/flutter-go-web-0.0.1)
<<<<<<< HEAD
<<<<<<< HEAD
<img src="https://img.alicdn.com/tfs/TB180.kOhYaK1RjSZFnXXa80pXa-442-420.png" width="200px">
=======
<img src="https://img.alicdn.com/tfs/TB1jGgfQ7voK1RjSZFNXXcxMVXa-438-426.png" width="200px">
>>>>>>> develop
=======
- [x] [ `Flutter Go Widget` `pull request` rules ( the third )](https://github.com/alibaba/flutter-go/blob/master/docs/contribute.md)
>>>>>>> dxj/master
Iphone download URL:
No
- [x] user center (yourself `widget`)
- login (with `GitHub`)
- search (search about `Flutter`)
- favorite component (save online)
- issues (APP online `ISSUES`)
- favorite (APP favorite)
- [x] [ `go-cli` tool ](https://github.com/alibaba/flutter-go/blob/master/docs/widget.md)
- `Flutter Go` `pull request` tools
- [ build `Flutter Go Widget` standard template with terminal ](https://github.com/alibaba/flutter-go/blob/beta/docs/widget.md)
- `markdown` template (when merge master breach)
- [x] ` Flutter Go ` `APP` auto upgrade
- [ ] template sync ( pc, native )
- [ ] `Flutter Go` store
## Third part build
Because the content of ** flutter ** is updated faster, we can't enrich the content of the project faster, If you are willing to contribute to the development and learning of flutter, please see the [build instructions](https://github.com/alibaba/flutter-go/blob/master/docs/contribute.md) before you start, we will put the builder's avatar and nick to the websit.
## Logs
[resource](https://github.com/alibaba/flutter-go/blob/develop/CHANGE-LOG.md)
## Development specification
> we are based on the official [dart language specification](https://www.dartlang.org)。
[<< Flutter Go development specification >>](https://github.com/alibaba/flutter-go/blob/develop/Flutter_Go%20%E4%BB%A3%E7%A0%81%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83.md)
## The Flutter-Go Roadmap for 2019
> Considering Flutter's future changes and strategy variability, roadmap does not rule out some adjustments, but overall it will not change much.
<img src="https://img.alicdn.com/tfs/TB19UahQQzoK1RjSZFlXXai4VXa-1500-1106.png" width="600px">
## How to use
- checkout version
```dart
flutter --version
```
- run doctor
```dart
flutter doctor
```
- start app
```dart
flutter packages get
flutter run
```
- other issues
- https://flutterchina.club/setup-macos/
- https://flutter.dev/docs/get-started/install/macos
## Release
### Android:
- [Download](https://github.com/alibaba/flutter-go/blob/master/android/app/release/app-release.apk)
### Ios:
- AppStore search "Fluttergo"
## Development Environment
This Project need latest package, please update regularly.
- dart(version: 2.0.0)
- flutter(version: v1.0.0)
```dart
flutter --version
dart --version
pub --version
// Flutter (Channel beta, v1.7.8)
// Dart VM version: 2.4.0
// Pub 2.4.0
```
### Background

View File

@ -1,9 +1,44 @@
# Flutter Go
Language: [English](https://github.com/alibaba/flutter-go/blob/master/README-en.md) | [中文简体](https://github.com/alibaba/flutter-go/blob/master/README.md)
## Flutter Go
![https://img.alicdn.com/tfs/TB1OJkeHNYaK1RjSZFnXXa80pXa-229-229.png](https://img.alicdn.com/tfs/TB1OJkeHNYaK1RjSZFnXXa80pXa-229-229.png)
> 帮助开发者快速上手 Flutter **Flutter Go 1.0 Android版已正式发布**
> 一个帮助开发者快速上手的 `APP`
## 最新动态
### 🔥 `Flutter Go 2.0` 发布
> Flutter Go 2.0 秉承年初发布的 [The Flutter-Go Roadmap路线图 for 2019](https://github.com/alibaba/flutter-go#the-flutter-go-roadmap%E8%B7%AF%E7%BA%BF%E5%9B%BE-for-2019) 已经做了新版本的迭代,新版本如下新功能:
<h6>注:✔是本次发布内容</h6>
- [x] [ `Flutter Go` 官方网站 ](https://flutter-go.pub/website/) (官方消息,发布,学习)
- [x] [ `Flutter Go web` 版本](https://github.com/alibaba/flutter-go/tree/web/flutter-go-web-0.0.1) (web 版本学习帮助)
- [线上预览版 ](https://flutter-go.pub/flutter_go_web/)
- [项目地址 ](https://github.com/alibaba/flutter-go/tree/web/flutter-go-web-0.0.1)
- [x] [ `Flutter Go Widget` 的 `pull request` 提交规范(第三方共建)](https://github.com/alibaba/flutter-go/blob/master/docs/contribute.md)
- [x] 用户中心 (专属个人的`widget`案例)
- 用户登录(通过`GitHub`账户)
- 全网搜索 (全网搜索 `Flutter` 资讯)
- 收藏个人组件(保存到远端)
- 反馈建议 APP 在线 `ISSUES`
- 分享链接 APP分享
- [x] [ `go-cli` 工具 ](https://github.com/alibaba/flutter-go/blob/master/docs/widget.md)
- `Flutter Go``pull request` 工具
- [命令行 生成 `Flutter Go Widget` 标准公共模版](https://github.com/alibaba/flutter-go/blob/beta/docs/widget.md)
- `markdown` 模版动态化生成合并到master分支后
- [x] ` Flutter Go ` 官方 `APP` 版本自动升级
- [ ] 多端模版同步( pc端native端同步 )
- [ ] `Flutter Go` store
## 三方共建说明
由于 **flutter** 内容更新较快. 我们无法更快的丰富项目的内容. 如果您愿意为国内flutter的发展与学习贡献自己的力量, 请参考我们的 [共建说明](https://github.com/alibaba/flutter-go/blob/master/docs/contribute.md), 我们会将共建者的头像姓名贡献至我们的官网.
## 版本更新历史
> 按时间顺序,展示重要的提交更新内容。
@ -16,13 +51,41 @@ Language: [English](https://github.com/alibaba/flutter-go/blob/master/README-en.
[<< Flutter Go 开发规范第一版 >>](https://github.com/alibaba/flutter-go/blob/develop/Flutter_Go%20%E4%BB%A3%E7%A0%81%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83.md)
<<<<<<< HEAD
<<<<<<< HEAD
=======
## The Flutter-Go Roadmap路线图 for 2019
> 考虑到 Flutter 未来的变化和策略的可变性, roadmap 不排除有一定调整,但总体不会变化太大。
<img src="https://img.alicdn.com/tfs/TB19UahQQzoK1RjSZFlXXai4VXa-1500-1106.png" width="600px">
## 运行方式
- 查看一下版本号是否正确
```dart
flutter --version
```
- 运行以下命令查看是否需要安装其它依赖项来完成安装
```dart
flutter doctor
```
- 运行启动您的应用
```dart
flutter packages get
flutter run
```
- 如果有其他问题,请参考
- https://flutterchina.club/setup-macos/
- https://flutter.dev/docs/get-started/install/macos
>>>>>>> dxj/master
## Release安装包下载地址
### android正式版下载地址:
- 华为市场已上线,华为应用市场搜索 "Fluttergo"或者直接[点击下载](https://appstore.huawei.com/search/fluttergo)
<img src="https://img.alicdn.com/tfs/TB1LbEYarys3KVjSZFnXXXFzpXa-378-380.jpg" width=200>
- [直接 apk 文件下载](https://github.com/alibaba/flutter-go/blob/master/android/app/release/app-release.apk)
### iphone正式版下载地址:
@ -55,8 +118,17 @@ iphone下载地址: AppStore上面进行搜索fluttego
## 基础环境
本项目环境持续更新. 请定期更新各依赖包.
- dart(version: 2.0.0)
- flutter(version: v1.0.0)
```dart
// 运行如下命令
flutter --version
dart --version
pub --version
// 正确环境如下
// Flutter (Channel beta, v1.7.8)
// Dart VM version: 2.4.0
// Pub 2.4.0
```
### 背景

View File

@ -59,8 +59,23 @@ android {
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
manifestPlaceholders = [
JPUSH_PKGNAME : "com.alibaba.fluttergo",
JPUSH_APPKEY : "62eb07d227d1f11dd7fa6239", //JPush上注册的包名对应的appkey.
JPUSH_CHANNEL : "developer-default",
]
// ndk {
// //选择要添加的对应cpu类型的.so库。
// abiFilters 'armeabi', 'armeabi-v7a','x86', 'x86_64', 'mips'//, 'arm64-v8a'
// // 还可以添加 'x86', 'x86_64', 'mips', 'mips64'
// }
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
@ -94,6 +109,8 @@ dependencies {
///implementation 'com.google.firebase:firebase-perf:16.2.3'
// 登陆
////implementation 'com.google.firebase:firebase-auth:16.0.3'
}
//firebase
apply plugin: 'com.google.gms.google-services'

View File

@ -7,21 +7,22 @@
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MODE_WORLD_READABLE"/>
<uses-permission android:name="android.permission.MODE_WORLD_WRITEABLE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODE_WORLD_READABLE" />
<uses-permission android:name="android.permission.MODE_WORLD_WRITEABLE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name="io.flutter.app.FlutterApplication"
android:label="FlutterGo"
android:icon="@mipmap/ic_launcher_logo">
android:icon="@mipmap/ic_launcher_logo"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
@ -31,8 +32,8 @@
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
@ -44,7 +45,7 @@
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
android:resource="@xml/provider_paths" />
</provider>
<provider

BIN
assets/images/arrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
assets/images/gitHub.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -1,160 +0,0 @@
# flutter-common-widgets-app
### 使用背景
* 鉴于目前flutter官方庞大的小部件widget系统以及api文档只有文字描述而没有可视化实例。
* 我们开发这套app,可以系统的看到常用小部件widget的用法。
* 辅助初学者更快上手,flutter官方小部件widget
### 参考资料
* [flutter-widgets的官方库地址]( https://docs.flutter.kim/widgets/widgets-library.html )
* [flutter-widgets的官方目录集]( http://doc.flutter-dev.cn/widgets/ )
* [sqlitestudio 本地可视化工具] (https://sqlitestudio.pl/index.rvt)
### 分支命名及使用规范
* 分支命名规范
- 自己开发分支命名统一为 username yifeng
- 分支两条主线为 Master分支和develop分支
- Master作为发布分支develop作为开发测试分支、自己开发分支从dev checkout出去发布即 merge to master
* 分支合并规范
- 从最新的develop分支checkout出自己的开发分支
- 在自己开发开发分支开发完成后先去develop分支pull最新代码
- 将develop 分支最新代码 merge 到自己分支,确保无冲突
- 再切回develop分支merge自己开发分支代码确保无冲突且能正常运行
### commit 提交规范
* $git cz
* 用于说明 commit 的类别只允许使用下面7个标识。
- feat新功能feature
- fix修补bug
- docs文档documentation
- style 格式(不影响代码运行的变动)
- refactor重构即不是新增功能也不是修改bug的代码变动
- test增加测试
- chore构建过程或辅助工具的变动
### 代码规范
* 文件命名规范
- 文件命名使用下划线命名法hello_world
- 请使用英文进行命名,不允许使用拼音。命名要求具有可读性,尽量避免使用缩写与数字
- 未完待续
* 代码编码规范
- 文件编码统一使用 UTF-8 编码;
- 前端编码采用首字母小写驼峰法. Widget Class 必须采用首字母大写驼峰法.
### 文件目录结构(以LIb文件说明)
- lib
- main.dart 入口文件
- common 公共的method
- components widget
- generated
- model 存放模型, 不应该加入逻辑层
- router 路由
- views 展示界面
- widget (与components概念重合,废弃)
``` javascript
├── main.dart //入口文件
├── common 公共的method
│   ├── Style.dart
│   ├── eventBus.dart
│   ├── provider.dart
│   └── sql.dart
├── components //app展示框架用到的组件
│   ├── Input.dart
│   ├── List.dart
│   ├── Pagination.dart
│   ├── Pagination2.dart
│   ├── SearchInput.dart
│   └── homeBanner.dart
├── generated
│   └── i18n.dart
├── model //本地存放模型, 不应该加入逻辑层
│   ├── base.dart
│   ├── cat.dart
│   ├── story.dart
│   └── widget.dart
├── routers //路由
│   ├── application.dart
│   ├── router_handler.dart
│   └── routers.dart
├── views //app展示界面
│   ├── Detail.dart
│   ├── FirstPage.dart
│   ├── FourthPage.dart
│   ├── ThirdPage.dart
│   ├── category.dart
│   ├── demos
│   │   ├── home.dart
│   │   └── layout
│   │   ├── SamplePage.dart
│   │   └── layout_type.dart
│   └── widgetPage.dart
└── widgets
└── ... //下面详细说明
```
``` javascript
└── widgets // 对flutter所有元素和组件的分类
├── 404.dart
├── index.dart // widgets 的总入口文件
├── components // 组件的分类 (区别于上面的components)
│   └── index.dart
├── elements // 基础元素的分类
│   ├── index.dart // elements下的 elements 类型入口文件
│   ├── Form // elements下的 From 类型集合
│   │   ├── Button // button 元素,里面是 文件夹代表类名/index.dart
│   │   │   ├── FlatButton
│   │   │   │   └── index.dart
│   │   │   ├── RaisedButton
│   │   │   │   └── index.dart
│   │   │   └── index.dart
│   │   ├── CheckBox
│   │   ├── Input
│   │   ├── Radio
│   │   ├── Slider
│   │   ├── Switch
│   │   ├── Text
│   │   └── index.dart
│   ├── Frame // elements下的 Frame 类型集合
│   │   ├── Align
│   │   ├── Axis
│   │   ├── Box
│   │   ├── Expanded
│   │   ├── Layout
│   │   ├── Stack
│   │   ├── Table
│   │   └── spacing
│   └── Media // elements下的 Media 类型集合
│      ├── Canvas
│      ├── Icon
│      └── Image
└── themes
└── index.dart
```
```javascript
widget 里的文件结构,用来存放封装的逻辑组件, 文件目录应为, 类比rax
- widget // widget 下详细元素或组件的目录结构
- hello-world // 例如
- mods // (可选, 子模块)
- mocks // (可选)
- utils // (可选, 存放暂时的私有method)
- schema
- index.dart
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 360 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 673 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

View File

35
docs/contribute.md Normal file
View File

@ -0,0 +1,35 @@
# Flutter Go 共建
# 共建说明
由于 **Flutter 版本迭代速度较快**,产生的内容较多, 而我们**人力有限**无法更加全面快速的支持Flutter Go的日常维护迭代, 如果您对flutter go的共建感兴趣, 欢迎您来参与本项目的共建.
**凡是参与共建的成员. 我们会将您的头像与github个人地址收纳进我们的官方网站中.**
# 共建方式
1. 共建组件
- 本次更新, 开放了 **Widget 内容收录** 的功能, 您需要通过 [goCli](https://github.com/alibaba/flutter-go/blob/master/docs/go-cli.md)工具, 创建标准化组件编写markdown代码。
- 为了更好记录您的改动目的, 内容信息, 交流过程, 每一条PR都需要对应一条 **Issue**, 提交你发现的`BUG`或者想增加的`新功能`, 或者想要增加新的[共建组件](https://github.com/alibaba/flutter-go/blob/maseter/docs/widget.md),
- 首先选择你的`issue`在类型,然后通过 **Pull Request** 的形式将文章内容, api描述, 组件使用方法等加入进我们的Widget界面。
![](https://img.alicdn.com/tfs/TB1r3LEbKL2gK0jSZFmXXc7iXXa-858-317.png)
2. 提交文章和修改bug
- 您也可以将例如**日常bug.** **未来feature**等的功能性PR, 申请提交到我们的的主仓库。
# 参与共建
关于如何提PR请先阅读以下文档
- [如何向仓库提交 Pull Request](https://github.com/alibaba/flutter-go/blob/master/docs/push-pr.md)
- [dart 代码规范](https://github.com/alibaba/flutter-go/blob/master/Flutter_Go%20%E4%BB%A3%E7%A0%81%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83.md)
- [如何使用go-cli 创建 Widget Page](https://github.com/alibaba/flutter-go/blob/master/docs/widget.md)
# 贡献指南
此项目遵循[贡献者行为准则](https://github.com/spring-projects/spring-framework/blob/master/CODE_OF_CONDUCT.adoc)。参与此项目即表示您同意遵守其条款.

81
docs/go-cli.md Normal file
View File

@ -0,0 +1,81 @@
# GoCli 使用说明
## 安装
获取最新flutterGo代码分之后. 在项目下会有 **go-cli** 的文件夹.
首先进入该文件夹并安装go-cli所需要的依赖
```
cd go-cli
pub get
```
然后使用pub global命令将文件包注册到全局
```
pub global activate --source path /{your project absolute path}/flutter-go/go-cli
```
使用pub global list命令查看全局包列表 如果看到有 **goCli 1.0.0**则证明安装成功
```
goCli 1.0.0 at path "/{youpath}/flutter-go/go-cli"
```
### 命令: goCli createPage
初始化并创建一个Widget详情页, 通常来说. 当我们需要在 **WIDGET 界面**下. 新加入一个Widget页, 执行该条命令, 会根据您的输入, 自动在本项目中创建对应的文件夹, 并记录相关配置信息, 在创建的目录中, 您可以通过编写markdown代码, 进行文章内容的编写.
![](https://img.alicdn.com/tfs/TB1ea5TdkL0gK0jSZFxXXXWHVXa-948-254.png)
### 命令: goCli createDemo
初始化并创建一个可实例化的Widget Demo(实例块), 按照在命令行中的提示, 输入我们的相关信息, 我们会创建一个 关于demo 的文件夹. 并会得到一个唯一的 **ID**. 我们可以通过这条ID,在我们的markdown代码中, 进行直接调用.
![](https://img.alicdn.com/tfs/TB1lAqVdhD1gK0jSZFyXXciOVXa-1070-206.png)
例如:
```
[demo:1a29aa8e_32ae_4241_9c8a_5c9e1f92b096]
```
### 命令: goCli build
将本地的界面与实例资源进行打包开成统一的独立的入口. 在拉取flutter-go的项目代码后. 需要执行当前命令. 否则会报错.
![](https://img.alicdn.com/tfs/TB1gAWRdXP7gK0jSZFjXXc5aXXa-988-116.png)
### goCli watch
动态便宜Widget Page, 动态进行markdown => dart 代码的转换. 通常在我们编辑Widget page的index.md的时候进行文件监听. 动态生成, 进行本地热更新.
## 注意
- 在修改**page\_demo\_package**或者standard\_pages目录下的文件操作时. 请先执行 **goCLi watch**
- **name**, **author** 字段必须使用英文开头, 不允许使用特殊符号. 正常的示范 name ='name_test' author = 'abcdefg';
- 以下文件目录, 显示**不可人为修改的文件**, 凡是被**合进master主分支的代码**不允许进行任何修改.
```
// demo 文件结构
demoName_yourName_1a29aa8e_32ae_4241_9c8a_5c9e1f92b096/
├── .demo.json (不可人为修改)
├── index.dart (不可人为修改)
└── src
└── index.dart (可修改)
// widget page 文件结构
standard_pages/
├── index.dart (不可人为修改)
└── standard_sanfan_ee4feb8e_32ae_4241_9c8a_5c9e1f92b096
├── .page.json (不可人为修改)
├── index.dart (不可人为修改)
└── index.md (可修改)
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

35
docs/push-pr.md Normal file
View File

@ -0,0 +1,35 @@
# 如何为一个项目提PR
## PR 的含义
PR的全称是 **pull request**, 可以理解成. 让开源项目拉取合并他方的请求.
## pull request
1. 将 开源flutter go项目 fork到我们自己的仓库.
![如何fock项目](https://img.alicdn.com/tfs/TB1XbnDbQH0gK0jSZPiXXavapXa-1425-672.gif)
2. 将Fork的仓库 clone 到本地,进行本地修改.
3. 将改动push到自己的仓库中
```
git add {some change file}
git commit ...
git push origin {your branch}
```
4. 登陆github, 从**自己的仓库**向**开源项目仓库** 发起 **pull request** (合并申请);
过程参考:
![如何提pr](https://img.alicdn.com/tfs/TB1zV_BbKL2gK0jSZPhXXahvXXa-1425-672.gif)
5. 开源项目维护者会review您的 **pull request**,展开讨论或者修改, 一旦通过审核,开源项目维护者合并该分支到正式仓库然后并关闭合并申请。

116
docs/widget.md Normal file
View File

@ -0,0 +1,116 @@
# 如何在Widget目录新增界面
> goCli是我们为了引入第三方页面编写的脚本命令. 向Widget新增页面时, 需要安装goCli脚本到全局.
## 安装goCli
获取最新flutterGo代码分之后. 在项目下会有 **go-cli** 的文件夹.
首先进入该文件夹并安装go-cli所需要的依赖
```
cd go-cli
pub get
```
然后使用pub global命令将文件包注册到全局
```
pub global activate --source path /{your project absolute path}/flutter-go/go-cli
```
使用pub global list命令查看全局包列表 如果看到有 **goCli 1.0.0**则证明安装成功
```
goCli 1.0.0 at path "/{youpath}/flutter-go/go-cli"
```
> 更多关于 **goCli** 请参考 [go-cli(共建工具)](https://github.com/alibaba/flutter-go/blob/beta/docs/go-cli.md) 文档
## 新建 Widget
在Widget列表页, 我们设有一个组, 名叫 **Developer**, 这个分组的作用是用来展示第三方作者提交的内容. 开发状态下正常情况下会显示以下内容
<img src="https://img.alicdn.com/tfs/TB1RCfZc1H2gK0jSZJnXXaT1FXa-798-1582.png" width='300px' />
在项目的根目录下使用 **goCLi createPage** 固定命令, 按照命令行提示信息. 输入新建界面的相关信息, 工具会自动的在 **lib/standard_pages/** 文件夹下创建一个Widget文件夹
```
goCli createPage
```
![](https://img.alicdn.com/tfs/TB1C9qKdoY1gK0jSZFCXXcwqXXa-1314-928.png)
按照以上操作会得到以下信息输出:
```
{
界面位于 : lib/standard_pages/name_author_06819c62_42ae_4241_9c8a_5c9e1f92b096
Id : 06819c62_42ae_4241_9c8a_5c9e1f92b096
文件夹名称 : name_author_06819c62_42ae_4241_9c8a_5c9e1f92b096
}
```
### 字段注意事项
**name** 必须**英文开头**, 统一用小写的英文字母,数字和下划线的组合,不得包含汉字空格和特殊字符, 需要与文章内容相关
**author** 可以为中文英文以及任意组合, 但是不得有歧义, 暴力, 辱骂等词汇, 否则可能会被拒绝合并
**desc** 相关的简要描述, 需要对添加的组件或者界面进行简要描述, 方便后期搜索引擎采集
**email** 创建者的邮箱
## 查看创建的Widvet
为了能正确的加载出新的界面, 建议重新启动当前项目. 在**Widget => Developer => 本地代码**中,您可以找到您新建的界面
<image src='https://img.alicdn.com/tfs/TB1eNLYc7Y2gK0jSZFgXXc5OFXa-744-722.png' width='300px' />
> 注意在android studio中, 有些情况下会无法在 **project** 目录中看到新创建的界面, 通常工程重启后. 会显示出新创建的文件
## 编辑界面
为了能动态的将**markdown**转化成**Widget 页面可识别**的内容, 再您更新widget页面的markdown文件之前, 请先执行脚本 **goCli Watch**, 以便在更改Widget页面时, 动态更新我们详情页的内容.
目标详情页
```
lib/standard_pages/standard_for_slider_sanfan_8ab2b5c2_42ae_4241_9c8a_5c9e1f92b096/index.md
```
参考:
![](https://img.alicdn.com/tfs/TB1cHLZc.T1gK0jSZFhXXaAtVXa-1393-760.gif)
## 引用Flutter 实例
如何在页面中引用flutter widget实例请参考: [WidgetDemo](https://github.com/alibaba/flutter-go/blob/master/go-cli/utils/tpl.md)
## 申请合并master
当我们的本地功能调试没有问题. 想要申请合并到主分支时.需要按以下流程进行
1.新建issue, 按照page about类型模板, 填写需要的相关数据
![](https://img.alicdn.com/tfs/TB1YMkCdUH1gK0jSZSyXXXtlpXa-805-354.png)
2.创建pr, 标题简要描述界面内容. 内容框填写issueID 例如 "#12"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

110
go-cli/Readme.md Normal file
View File

@ -0,0 +1,110 @@
# GoCli 使用方式
## 安装
获取最新flutterGo代码分之后. 在源文件下会有 **go-cli** 的文件.
首先进入该文件夹并安装go-cli所需要的依赖
```
cd go-cli
pub get
```
然后使用pub global命令将文件包注册到全局
```
pub global activate --source path /{your flutter go absolute path}/fluttergo/go-cli
```
使用pub global list命令查看全局包列表 如果看到有 **goCli 1.0.0**则证明安装成功
```
goCli 1.0.0 at path "/{youpath}/flutter-go/go-cli"
```
## 使用方式
现在支持以下几种命令
- createDemo 新增flutter go demo.
- createPage 新增flutter go page.
- watch 动态生成文档与demo相关
- build 生成文档与demo相关
### createDemo
动态生成widget demo, 可以创建demo.以便详情页中使用
在flutter go 根文件下通过命令行输入以上命令可以进行以下操作
[✓] 请输入新增加的demo名称? demoName
[✓] 请输入您的姓名(使用英文) yourName
[✓] 请输入您的github的email地址 yourEmail
[✓] 请输入您demo的描述 这是一个测试的标准demo
在完成以上操作后, 可以得到这样的输出:
```
------------------
您新增的组件信息如下
==================
{
name : demoName
author : yourName
email : yourEmail
desc : 这是一个测试的标准demo
}
==================
[✓] Is this the config you want ? (Y/n) y
{
新建的demo文件位于 : /flutter go/lib/page_demo_package/demoName_yourName_1a29aa8e_32ae_4241_9c8a_5c9e1f92b096
demoId为 : 1a29aa8e_32ae_4241_9c8a_5c9e1f92b096
markdown中调用方式 : [demo:1a29aa8e_32ae_4241_9c8a_5c9e1f92b096]
}
```
您可以在任意详情页中, 通过以下方式调用
```
[demo: 1a29aa8e_32ae_4241_9c8a_5c9e1f92b096]
```
### createPage
使用方式同上. 通过该命令可以创建标准的详情页.您可以通过修改index.md进行动态的更新您所创建的详情页.
目录结构为
```
standard_pages/
├── index.dart (不可人为修改)
└── standard_sanfan_ee4feb8e_32ae_4241_9c8a_5c9e1f92b096
├── .page.json (不可人为修改)
├── index.dart (不可人为修改)
└── index.md (可修改)
```
### watch
监听并编译standard_pages与page_demo_package下的的文件改动. 动态处理demo目录与文件markdown转化等.
## 注意
- 在修改page_demo_package或者standard_pages目录下的文件操作时. 建议在flutterGo目录执行goCLi watch 开启文件动态编译
- name, author 字段必须使用英文开头, 不允许使用特殊符号. 正常的示范 name ='name_test' author = 'abcdefg';
- 暂时阶段demo与page,一经过创建不允许修改名称作者等信息. 凡是被收录进主分支的不允许被删除

17
go-cli/bin/goCli.dart Normal file
View File

@ -0,0 +1,17 @@
import 'package:args/args.dart'; // 使用其中两个类ArgParser和ArgResults
import 'package:args/command_runner.dart';
import '../src/cli_command_runder.dart';
ArgResults argResults; // 声明ArgResults类型的顶级变量保存解析的参数结果
// 同时argResults也是ArgResults的实例
void main(List<String> args) async {
// createDemo();
try {
await run(args);
} on UsageException catch (e) {
print(' ');
print(e.usage);
}
}

3
go-cli/config.json Normal file
View File

@ -0,0 +1,3 @@
{
"name": "sanfan"
}

24
go-cli/pubspec.yaml Normal file
View File

@ -0,0 +1,24 @@
name: goCli
description: bin_go
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# Read more about versioning at semver.org.
version: 1.0.0
executables:
goCli:
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
args: '^1.5.1'
dart_inquirer: '^1.0.0'
watcher: ^0.9.7+10
mustache: ^1.1.1
dev_dependencies:

View File

@ -0,0 +1,94 @@
import 'dart:io';
import 'dart:convert';
import '../../utils/util.dart';
import '../config.dart';
import '../exception/demo.dart';
Future<List> buildDemoListJson() async {
List<FileSystemEntity> childList = await readeDirChildren(TARGET_DEMO_DIC, false);
List<String> demoPathList = [];
List<Map<String, dynamic>> detailList = []; // 存放所有demo的详情的列表
for(FileSystemEntity entity in childList) {
//文件、目录和链接都继承自FileSystemEntity
//FileSystemEntity.type静态函数返回值为FileSystemEntityType
//FileSystemEntityType有三个常量
//Directory、FILE、LINK、NOT_FOUND
//FileSystemEntity.isFile .isLink .isDerectory可用于判断类型
if (await FileSystemEntity.isDirectory(entity.path)) {
try {
await checkDemo(entity.path);
demoPathList.add(entity.path);
} on InvalidDemo catch (e) {
print("不存在 $e");
}
}
}
for (String dicPath in demoPathList) {
String target = '$dicPath/.demo.json';
String jsonString = await readeFile(target);
try {
Map<String, dynamic> item = json.decode(jsonString);
detailList.add(item);
} catch (err) {
print("err $err");
throw new Exception('$dicPath');
}
}
print("本次编译: 获取${detailList.length}条demo数据");
String demoTplString = renderDemosDart(detailList);
// 生成 page_demo_package/index.dart
writeContent2Path(TARGET_DEMO_DIC, 'index.dart', demoTplString.replaceAll(new RegExp('-'), '_'));
// 生成 page_demo_package/.demo.dart
writeContent2Path(TARGET_DEMO_DIC, '.demo.json', json.encode(detailList));
return Future(() => childList);
// return ;
}
String renderDemosDart(List<Map<String, dynamic>> data) {
// 自定义前缀 避免出现数字非法字符等
String pre = "StandardDemo";
String head = '';
String foot = 'var demoObjects = { \r\n';
for (int i = 0; i < data.length; i++) {
Map<String, dynamic> item = data[i];
String demoImportName = '${item['name']}_${item['id']}';
head += "import '${item['name']}_${item['author']}_${item['id']}/index.dart' as StandardDemo_$demoImportName;\r\n";
foot += " '${item['id']}': ${pre}_${demoImportName}.demoWidgets";
if (i != data.length - 1) {
foot += ',\r\n';
}
}
foot += "\r\n};";
return head + foot;
}
Future<bool> checkDemo(String path) async {
List files = [
'index.dart',
'.demo.json',
'src/'
];
for (String name in files) {
bool isDic = name.indexOf('/') != -1;
bool isExist ;
String detailPath = '$path/$name';
if (isDic) {
isExist = await Directory(detailPath).exists();
} else {
isExist = await File(detailPath).exists();
}
if (!isExist) {
throw new InvalidDemo('$path$name not exit');
}
}
return Future(() => true);
}

View File

@ -0,0 +1,185 @@
import 'dart:io';
import 'dart:convert';
import 'package:mustache/mustache.dart';
import 'package:path/path.dart' as p;
import '../../utils/util.dart';
import '../config.dart';
import '../exception/demo.dart';
String prettyJson(Map json) {
String res = "{";
json.forEach((k, v) {
res += (
"\t'$k': '$v'");
});
res +='}';
return res;
}
Future<List> buildPageListJson() async {
List<FileSystemEntity> childList = await readeDirChildren(TARGET_PAGE_DIC, false);
List<String> pagePathList = [];
List<Map<String, dynamic>> detailList = []; // 存放所有demo的详情的列表
int errCount = 0;
int pageCount = 0;
for(FileSystemEntity entity in childList) {
//文件、目录和链接都继承自FileSystemEntity
//FileSystemEntity.type静态函数返回值为FileSystemEntityType
//FileSystemEntityType有三个常量
//Directory、FILE、LINK、NOT_FOUND
//FileSystemEntity.isFile .isLink .isDerectory可用于判断类型
if (await FileSystemEntity.isDirectory(entity.path)) {
pageCount++;
try {
await checkPage(entity.path);
pagePathList.add(entity.path);
} on InvalidDemo catch (e) {
errCount++;
print("不存在 $e");
}
}
}
for (String dicPath in pagePathList) {
String target = '$dicPath/.page.json';
String jsonString = await readeFile(target);
try {
Map<String, dynamic> item = json.decode(jsonString);
detailList.add(item);
} catch (err) {
print("err $err");
throw new Exception('$dicPath');
}
}
print("本次编译: 总${pageCount}个界面, 成功${detailList.length}条, 失败${errCount}");
String demoTplString = renderPagesDart(detailList);
//
// // 生成 page_demo_package/index.dart
writeContent2Path(TARGET_PAGE_DIC, 'index.dart', demoTplString.replaceAll(new RegExp('-'), '_'));
// // 生成 page_demo_package/.demo.dart
writeContent2Path(TARGET_PAGE_DIC, '.pages.json', json.encode(detailList));
return Future(() => childList);
// return ;
}
String renderPagesDart(List<Map<String, dynamic>> data) {
var source = '''
{{# pages }}
import '{{ name }}_{{ author }}_{{ id }}/index.dart' as StandardPage_{{ name }}_{{ id }};
{{/ pages }}
class StandardPages {
Map<String, String> standardPages;
Map<String, String> getPages() {
return {
"0": "0" {{# pages }},
"{{ id }}" : StandardPage_{{ name }}_{{ id }}.getMd()
{{/ pages }}
};
}
List<Map<String, String>> getLocalList() {
return [
{}{{# pages }},
{ "id": "{{ id }}", "name": "{{ name }}", "email": "{{ email }}", "author": "{{ author }}"}
{{/ pages }}
];
}
}
''';
var template = new Template(source, name: 'template-filename.html');
// 自定义前缀 避免出现数字非法字符等
Map<String, List> formatData = {
"pages": data
};
String output = template.renderString(formatData);
return output;
}
Future<bool> checkPage(String path) async {
List files = [
'index.dart',
'index.md',
'.page.json'
];
for (String name in files) {
bool isDic = name.indexOf('/') != -1;
bool isExist ;
String detailPath = '$path/$name';
if (isDic) {
isExist = await Directory(detailPath).exists();
} else {
isExist = await File(detailPath).exists();
}
if (!isExist) {
throw new InvalidDemo('$path$name not exit');
}
}
return Future(() => true);
}
Future<void> transformMd2Dart(String path) async{
print("pathLL: $path");
String mdContent = await readeFile(p.absolute(path,'index.md'));
String result = """
String getMd() {
return \"\"\"
${mdContent}\"\"\";
}
""";
writeContent2Path(p.absolute(path), 'index.dart', result);
return '';
}
//main() {
// buildPageListJson();
//}
////
//// Created with Android Studio.
//// User: 三帆
//// Date: 25/05/2019
//// Time: 21:23
//// email: sanfan.hx@alibaba-inc.com
//// target: 该文件用在打包后的代码中.日常开发的时候, 获取markdown不走该目录
////
//import 'package:flutter/material.dart';
//import 'page1_hanxu_172ba42f_0520_401e_b568_ba7f7f6835e4/index.dart' as page1_hanxu_172ba42f_0520_401e_b568_ba7f7f6835e4;
//
//
//class StandardPages {
// Map<String, String> standardPages;
// Map<String, String> getPages() {
// return {
// 'page1_hanxu_172ba42f_0520_401e_b568_ba7f7f6835e4': page1_hanxu_172ba42f_0520_401e_b568_ba7f7f6835e4.stringMd
// };
// }
//}
//var stringMd = """# page
//
//this is page markdown
//
//you can load demo like this
//
//```
//[demo: xxxid]
//```
//
//""";
//

View File

@ -0,0 +1,42 @@
import 'dart:async';
import 'dart:io';
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
//import './version.dart';
import './command/create_demo.dart';
import './command/create_page.dart';
import './command/watch_md.dart';
import './command/build.dart';
Future<int> run(List<String> args) => _CommandRunner().run(args);
class _CommandRunner extends CommandRunner<int> {
_CommandRunner() : super('goCli', 'A tool to develop flutter go projects.') {
argParser.addFlag('version',
negatable: false, help: 'Prints the version of goCi.');
addCommand(CreateDemoCommand());
addCommand(CreatePageCommand());
addCommand(WatchCommand());
addCommand(Build());
}
@override
Future<int> runCommand(ArgResults topLevelResults) async {
bool isProject = await Directory('./go-cli').exists();
// 防止用户在gocli下运行
if (!isProject) {
print("请在fluttergo项目根目录中运行,而不是go-cli目录中");
return 0;
}
if (topLevelResults['version'] as bool) {
return 0;
}
// In the case of `help`, `null` is returned. Treat that as success.
return await super.runCommand(topLevelResults) ?? 0;
}
}

View File

@ -0,0 +1,32 @@
//
// Created with Android Studio.
// User: 三帆
// Date: 30/07/2019
// Time: 16:51
// email: sanfan.hx@alibaba-inc.com
// target: build
//
import 'package:args/command_runner.dart';
import '../build/build_demo_list.dart';
import '../build/build_page_list.dart';
import 'dart:async';
class Build extends Command<int> {
@override
final name = 'build';
@override
final description = '生成索引等';
@override
Future<int> run() async {
buildPageListJson();
buildDemoListJson();
return 0;
}
}

View File

@ -0,0 +1,135 @@
import 'package:args/args.dart'; // 使用其中两个类ArgParser和ArgResults
import 'package:dart_inquirer/dart_inquirer.dart';
import 'package:path/path.dart' as p;
import 'package:args/command_runner.dart';
import '../build/build_demo_list.dart';
import '../config.dart';
import '../../utils/util.dart';
ArgResults argResults; // 声明ArgResults类型的顶级变量保存解析的参数结果
class DemoDetail {
String name;
String author;
String email;
String desc;
String id;
DemoDetail.fromJson(Map<dynamic, dynamic> json) {
name = json['name'].trim();
author = json['author'].trim();
email = json['email'].trim();
desc = json['desc'].trim();
id = json['id'] ?? generateId();
}
}
// 同时argResults也是ArgResults的实例
void createDemo() async {
List<Question> questions = [
InputQuestion('name', '请输入新增加的demo名称?'),
InputQuestion('author', '请输入您的姓名(使用英文)'),
InputQuestion('email', '请输入您的github的email地址'),
InputQuestion('desc', '请输入您demo的描述'),
];
Map<dynamic, dynamic> answers = {};
// 获取初次信息
Prompt prompt = Prompt(questions);
DemoDetail demoDetail;
answers = await prompt.execute();
print(Seperator());
print('您新增的组件信息如下');
print(Seperator('='));
prettyPrintJson(answers);
print(Seperator('='));
questions =[ConfirmQuestion('confirm', 'Is this the config you want ?')];
prompt = Prompt(questions);
Map confirmAnswers = await prompt.execute();
if (confirmAnswers['confirm'] != true) {
return createDemo();
}
demoDetail = DemoDetail.fromJson(answers);
var demoPath = '$TARGET_DEMO_DIC/${demoDetail.name}_${demoDetail.author}_${demoDetail.id}';
// 创建root文件
await createFile(demoPath);
await createFile('$demoPath/src');
// print("demoPath>>>> ${environmentVars['PWD']}/${demoPath}");
writeContent2Path('$demoPath/src/', 'index.dart', """
import 'package:flutter/material.dart';
class Demo extends StatefulWidget {
@override
_State createState() => _State();
}
class _State extends State<Demo> {
@override
Widget build(BuildContext context) {
return Container(
child: Text("this is flutter go init demo"),
);
}
}
""");
writeContent2Path('$demoPath/', '.demo.json', """
{
"name": "${demoDetail.name}",
"screenShot": "",
"author":"${demoDetail.author}",
"email": "${demoDetail.email}",
"desc": "${demoDetail.desc}",
"id": "${demoDetail.id}"
}
""");
writeContent2Path('$demoPath/', 'index.dart', """
//
// Created with flutter go cli
// User: ${demoDetail.author}
// Time: ${new DateTime.now()}
// email: ${demoDetail.email}
// desc: ${demoDetail.desc}
//
import 'src/index.dart';
var demoWidgets = [
new Demo()
];
""");
// format('{color.red}Invalid demo happends: $details {color.normal}');
prettyPrintJson({
'新建的demo文件位于': p.absolute((demoPath)),
'demoId为': demoDetail.id,
'markdown中调用方式': '[demo:${demoDetail.id}]'
});
buildDemoListJson();
}
class CreateDemoCommand extends Command<int> {
@override
final name = 'createDemo';
@override
final description = '新增flutter go demo.';
CreateDemoCommand() {
}
@override
Future<int> run() async {
createDemo();
return 0;
}
}

View File

@ -0,0 +1,124 @@
import 'dart:io';
import 'package:args/args.dart'; // 使用其中两个类ArgParser和ArgResults
import 'package:dart_inquirer/dart_inquirer.dart';
import 'package:args/command_runner.dart';
import '../build/build_page_list.dart';
import '../config.dart';
import '../../utils/util.dart';
var pageMarkdown = """
# page
this is page markdown
you can load demo like this
```
[demo: xxxid]
```
""";
ArgResults argResults; // 声明ArgResults类型的顶级变量保存解析的参数结果
class PageDetail {
String name;
String author;
String title;
String email;
String desc;
String id;
PageDetail.fromJson(Map<dynamic, dynamic> json) {
name = json['name'];
author = json['author'];
title = json['title'];
email = json['email'];
desc = json['desc'];
id = json['id'] ?? generateId();
}
}
// 同时argResults也是ArgResults的实例
void createPage() async {
Map environmentVars = Platform.environment;
List<Question> questions = [
InputQuestion('name', '请输入文件名称?'),
InputQuestion('title', '请输入界面名称?'),
InputQuestion('author', '请输入您的姓名(使用英文)'),
InputQuestion('email', '请输入您的email地址'),
InputQuestion('desc', '请输入您界面的简要'),
];
Map<dynamic, dynamic> answers = {};
// 获取初次信息
Prompt prompt = Prompt(questions);
PageDetail pageDetail;
answers = await prompt.execute();
print(Seperator());
print('您新增的界面信息如下');
print(Seperator('='));
prettyPrintJson(answers);
print(Seperator('='));
questions =[ConfirmQuestion('confirm', 'Is this the config you want ?')];
prompt = Prompt(questions);
Map confirmAnswers = await prompt.execute();
if (confirmAnswers['confirm'] != true) {
return createPage();
}
pageDetail = PageDetail.fromJson(answers);
var demoPath = '$TARGET_PAGE_DIC/${pageDetail.name}_${pageDetail.author}_${pageDetail.id}';
// 创建root文件
await createFile(demoPath);
pageMarkdown = await readeFile("go-cli/utils/tpl.md");
writeContent2Path('$demoPath/', 'index.dart', """
String getMd() {
return \"\"\"
${pageMarkdown}\"\"\";
}
""");
writeContent2Path('$demoPath/', '.page.json', """
{
"name": "${pageDetail.name}",
"screenShot": "",
"author":"${pageDetail.author}",
"title":"${pageDetail.title}",
"email": "${pageDetail.email}",
"desc": "${pageDetail.desc}",
"id": "${pageDetail.id}"
}
""");
writeContent2Path('$demoPath/', 'index.md', pageMarkdown);
buildPageListJson();
prettyPrintJson({
'界面位于': demoPath,
'Id': pageDetail.id,
'文件夹名称': '${pageDetail.name}_${pageDetail.author}_${pageDetail.id}'
});
}
class CreatePageCommand extends Command<int> {
@override
final name = 'createPage';
@override
final description = '新增flutter go page.';
CreateDemoCommand() {
}
@override
Future<int> run() async {
createPage();
return 0;
}
}

View File

@ -0,0 +1,97 @@
//
// Created with Android Studio.
// User: 三帆
// Date: 08/06/2019
// Time: 16:34
// email: sanfan.hx@alibaba-inc.com
// target: 监听demo与md
//
import 'package:path/path.dart' as p;
import 'package:args/command_runner.dart';
import '../build/build_demo_list.dart';
import '../build/build_page_list.dart';
import 'package:watcher/watcher.dart';
import '../config.dart';
import 'dart:async';
void watch() {
Timer _changeTimer;
List<String> demoIgnore = [
'.demo.json',
'index.dart',
'info.json',
'readme.md',
];
var watcherDemo = DirectoryWatcher(p.absolute('$TARGET_DEMO_DIC'));
watcherDemo.events.listen((event) {
if (isIgnore(demoIgnore, TARGET_DEMO_DIC, event.path)) {
return ;
}
if (event.type == ChangeType.ADD || event.type == ChangeType.REMOVE) {
if (_changeTimer != null && _changeTimer.isActive) {
_changeTimer.cancel();
}
_changeTimer = new Timer(Duration(milliseconds: 1000), () {
buildDemoListJson();
});
}
}, onError: (error) {
print('watch 发生错误: $error');
});
List<String> pageIgnore = [
'index.dart',
'.pages.json'
];
var watcherPage = DirectoryWatcher(p.absolute('$TARGET_PAGE_DIC'));
watcherPage.events.listen((event) {
if (isIgnore(pageIgnore, TARGET_PAGE_DIC, event.path)) {
return ;
}
if (event.type == ChangeType.ADD || event.type == ChangeType.REMOVE) {
print("buildPageListJson:::");
buildPageListJson();
return ;
}
if (event.type == ChangeType.MODIFY) {
if (event.path.contains('index.md')) {
transformMd2Dart(event.path.replaceAll('/index.md', ''));
}
return ;
}
print(event);
});
}
bool isIgnore (List<String> ignorePath, parentPath, currentPath) {
for (String ignore in ignorePath) {
String path = p.absolute(parentPath, ignore);
if (currentPath.contains(path)) {
// print("修改的文件, 是忽略列表中的文件, 跳过编译!");
return true;
}
}
return false;
}
class WatchCommand extends Command<int> {
@override
final name = 'watch';
@override
final description = '动态生成文档与demo相关';
CreateDemoCommand() {
}
@override
Future<int> run() async {
watch();
return 0;
}
}

4
go-cli/src/config.dart Normal file
View File

@ -0,0 +1,4 @@
// 生成Demo的目录位置
const TARGET_PAGE_DIC = 'lib/standard_pages';
const TARGET_DEMO_DIC = 'lib/page_demo_package';

View File

@ -0,0 +1,21 @@
//
// Created with Android Studio.
// User: 三帆
// Date: 25/05/2019
// Time: 21:20
// email: sanfan.hx@alibaba-inc.com
// target: xxx
//
import 'package:console/console.dart';
class InvalidDemo implements Exception {
final String details;
InvalidDemo(this.details);
@override
String toString() {
return format('{color.red}Invalid demo happends: $details {color.normal}');
}
}

1
go-cli/src/version.dart Normal file
View File

@ -0,0 +1 @@
const packageVersion = '1.0.0';

60
go-cli/utils/tpl.md Normal file
View File

@ -0,0 +1,60 @@
# 标准的详情页
您可以在这个界面中, 编写大多数的markdown文案, 他会在 **goCli watch** 下同步被编译成 **dart** 文件
您可以通过goCli固定命令创建详情页所需要的 **Flutter 实例**
```
goCLi createDemo
```
在flutter go 根文件下通过命令行输入以上命令可以进行以下操作
[✓] 请输入新增加的demo名称? demoName
[✓] 请输入您的姓名(使用英文) yourName
[✓] 请输入您的github的email地址 yourEmail
[✓] 请输入您demo的描述 这是一个测试的标准demo
在完成以上操作后, 可以得到这样的输出:
```
------------------
您新增的组件信息如下
==================
{
name : demoName
author : yourName
email : yourEmail
desc : 这是一个测试的标准demo
}
==================
[✓] Is this the config you want ? (Y/n) y
{
新建的demo文件位于 : /flutter go/lib/page_demo_package/demoName_yourName_1a29aa8e_32ae_4241_9c8a_5c9e1f92b096
demoId为 : 1a29aa8e_32ae_4241_9c8a_5c9e1f92b096
markdown中调用方式 : [demo:1a29aa8e_32ae_4241_9c8a_5c9e1f92b096]
}
```
您可以在任意详情页中, 通过以下方式调用
```
[demo: 1a29aa8e_32ae_4241_9c8a_5c9e1f92b096]
```
# 注意事项
**name** 必须**英文开头**, 统一用小写的英文字母,数字和下划线的组合,不得包含汉字空格和特殊字符, 需要与文章内容相关
**author** 可以为中文英文以及任意组合, 但是不得有歧义, 暴力, 辱骂等词汇, 否则可能会被拒绝合并
**desc** 相关的简要描述, 需要对添加的组件或者界面进行简要描述, 方便后期搜索引擎采集
**email** 创建者的邮箱

64
go-cli/utils/util.dart Normal file
View File

@ -0,0 +1,64 @@
import 'dart:io';
import 'dart:math';
Future<bool> createFile(String path) async {
final tempDic = new Directory(path);
var exits = await tempDic.exists();
if (exits) {
print("文件当前已存在");
return Future(() => false);
}
await tempDic.createSync(recursive: true);
return Future(() => true);
}
Future<String> readeFile(String path) async {
String content = await new File(path).readAsString();
return Future(() => content);
}
// 该文件调用的时候. 必须存在父级文件夹
Future<void> writeContent2Path(String path,String fileName, String content) async {
var file = File('$path/$fileName');
var sink = file.openWrite();
sink.write(content);
await sink.flush();
await sink.close();
return Future.value();
}
String generateId() {
int d = DateTime.now().millisecondsSinceEpoch;
var random = new Random(1);
var template = 'xxxxxxxx_xxxx_4xxx_yxxx_xxxxxxxxxxxx';
var id = template.replaceAllMapped(new RegExp(r"[x|y]"), (c) {
var r = ((d + random.nextDouble() * 16) % 16).toInt();
d = d ~/ 16;
var t = c.group(0) == 'x' ? r : (1 & 0x3 | 0x8);
return t.toRadixString(16);
});
return id;
}
/// 该文件调用的时候. 必须存在父级文件夹
/// @param path 目录地址
/// @param recursive 是否显示子目录或者子文件
Future<List<FileSystemEntity>> readeDirChildren(String path, [bool recursive = false]) async {
try {
var dirParent = Directory(path);
Stream<FileSystemEntity> entityList = dirParent.list(recursive: false, followLinks: false);
List<FileSystemEntity> fileChildren = [];
await for(FileSystemEntity entity in entityList) {
fileChildren.add(entity);
}
return Future(() => fileChildren);
} catch (e) {
print('读取文件失败 ${e.toString()}');
return Future(() => []);
}
}
//void main() {
// readeFile('/Users/ontwo/Documents/ali/flutter/flutter-common-widgets-app/LICENSE');
//}

View File

@ -25,18 +25,23 @@
0828E4A52206936100A59437 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0828E4A42206936100A59437 /* Images.xcassets */; };
084A20882202E4FD00428FF5 /* flutter go.png in Resources */ = {isa = PBXBuildFile; fileRef = 084A20872202E4FD00428FF5 /* flutter go.png */; };
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
333E5DAE7FC10AC69FEC26C0 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DDA792F029EDD7A11295D192 /* libPods-Runner.a */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
17DB4C25EDB98B3648015B9E /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 813A089174EBE6F8695A172E /* libPods-Runner.a */; };
94722E5C22511D3600F63900 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 94722E5B22511D3600F63900 /* GoogleService-Info.plist */; };
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
FA240D7922F2857D003025F3 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAD0115F22F1B9DF0016E673 /* Flutter.framework */; };
FA240D7A22F2857D003025F3 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = FAD0115F22F1B9DF0016E673 /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
FA240D7B22F28581003025F3 /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAD0116122F1B9DF0016E673 /* App.framework */; };
FA240D7C22F28581003025F3 /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = FAD0116122F1B9DF0016E673 /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
FAD0116422F1B9DF0016E673 /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = FAD0115E22F1B9DF0016E673 /* Debug.xcconfig */; };
FAD0116522F1B9DF0016E673 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAD0115F22F1B9DF0016E673 /* Flutter.framework */; };
FAD0116622F1B9DF0016E673 /* Release.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = FAD0116022F1B9DF0016E673 /* Release.xcconfig */; };
FAD0116722F1B9DF0016E673 /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAD0116122F1B9DF0016E673 /* App.framework */; };
FAD0116822F1B9DF0016E673 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = FAD0116222F1B9DF0016E673 /* AppFrameworkInfo.plist */; };
FAD0116922F1B9DF0016E673 /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = FAD0116322F1B9DF0016E673 /* Generated.xcconfig */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -46,8 +51,8 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
FA240D7C22F28581003025F3 /* App.framework in Embed Frameworks */,
FA240D7A22F2857D003025F3 /* Flutter.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@ -72,26 +77,27 @@
0828E494220692B500A59437 /* iPhone XR Landscape.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPhone XR Landscape.png"; sourceTree = "<group>"; };
0828E4A42206936100A59437 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
084A20872202E4FD00428FF5 /* flutter go.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "flutter go.png"; sourceTree = "<group>"; };
10D9E78922B7651B003C2C98 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
813A089174EBE6F8695A172E /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
94722E5B22511D3600F63900 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A9941E6EA19A9CEF6B117A70 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
CBA6E34746642008D95A119D /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
DDA792F029EDD7A11295D192 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
A4868A865F318D337B7500AF /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
B7B77D3AD1E975E5BE03D770 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
FAD0115E22F1B9DF0016E673 /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
FAD0115F22F1B9DF0016E673 /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Flutter.framework; sourceTree = "<group>"; };
FAD0116022F1B9DF0016E673 /* Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
FAD0116122F1B9DF0016E673 /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = App.framework; sourceTree = "<group>"; };
FAD0116222F1B9DF0016E673 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = AppFrameworkInfo.plist; sourceTree = "<group>"; };
FAD0116322F1B9DF0016E673 /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Generated.xcconfig; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -99,9 +105,11 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
333E5DAE7FC10AC69FEC26C0 /* libPods-Runner.a in Frameworks */,
17DB4C25EDB98B3648015B9E /* libPods-Runner.a in Frameworks */,
FAD0116722F1B9DF0016E673 /* App.framework in Frameworks */,
FAD0116522F1B9DF0016E673 /* Flutter.framework in Frameworks */,
FA240D7922F2857D003025F3 /* Flutter.framework in Frameworks */,
FA240D7B22F28581003025F3 /* App.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -130,46 +138,24 @@
path = launch;
sourceTree = "<group>";
};
0C172CA58CDB230D5DA80034 /* Pods */ = {
8B83D3FCE2CD78ED2CD9BC84 /* Frameworks */ = {
isa = PBXGroup;
children = (
CBA6E34746642008D95A119D /* Pods-Runner.debug.xcconfig */,
A9941E6EA19A9CEF6B117A70 /* Pods-Runner.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
2EC8A3499721CE770475DCE7 /* Frameworks */ = {
isa = PBXGroup;
children = (
DDA792F029EDD7A11295D192 /* libPods-Runner.a */,
813A089174EBE6F8695A172E /* libPods-Runner.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
FAD0115D22F1B9DF0016E673 /* Flutter */,
0828E485220692A700A59437 /* launch */,
084A20872202E4FD00428FF5 /* flutter go.png */,
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
0C172CA58CDB230D5DA80034 /* Pods */,
2EC8A3499721CE770475DCE7 /* Frameworks */,
F1785F83FDEE22F813679AE5 /* Pods */,
8B83D3FCE2CD78ED2CD9BC84 /* Frameworks */,
);
sourceTree = "<group>";
};
@ -184,6 +170,7 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
10D9E78922B7651B003C2C98 /* Runner.entitlements */,
94722E5B22511D3600F63900 /* GoogleService-Info.plist */,
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
@ -207,6 +194,28 @@
name = "Supporting Files";
sourceTree = "<group>";
};
F1785F83FDEE22F813679AE5 /* Pods */ = {
isa = PBXGroup;
children = (
A4868A865F318D337B7500AF /* Pods-Runner.debug.xcconfig */,
B7B77D3AD1E975E5BE03D770 /* Pods-Runner.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
FAD0115D22F1B9DF0016E673 /* Flutter */ = {
isa = PBXGroup;
children = (
FAD0115E22F1B9DF0016E673 /* Debug.xcconfig */,
FAD0115F22F1B9DF0016E673 /* Flutter.framework */,
FAD0116022F1B9DF0016E673 /* Release.xcconfig */,
FAD0116122F1B9DF0016E673 /* App.framework */,
FAD0116222F1B9DF0016E673 /* AppFrameworkInfo.plist */,
FAD0116322F1B9DF0016E673 /* Generated.xcconfig */,
);
path = Flutter;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -214,15 +223,15 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
443E32A5789BE5CCDA6B5E59 /* [CP] Check Pods Manifest.lock */,
FBE7DB4E8DD084FE99B9ED05 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
C38E5EAE601417DA9DF11753 /* [CP] Embed Pods Frameworks */,
2432F011A7D713E4BFB3DC88 /* [CP] Copy Pods Resources */,
B34D03FFEA3831330E64E5C7 /* [CP] Embed Pods Frameworks */,
E54A6BDEF16ACE4A6988913A /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -239,22 +248,26 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1000;
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = 4WLT68XRNA;
ProvisioningStyle = Manual;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.Push = {
enabled = 1;
};
};
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
@ -273,6 +286,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FAD0116622F1B9DF0016E673 /* Release.xcconfig in Resources */,
0828E4A0220692B500A59437 /* iPad Landscape.png in Resources */,
0828E4A1220692B500A59437 /* iPhone XR Portrait.png in Resources */,
0828E49F220692B500A59437 /* iPhone XS Max Landscape.png in Resources */,
@ -280,18 +294,24 @@
0828E4A3220692B500A59437 /* iPhone XR Landscape.png in Resources */,
0828E4A2220692B500A59437 /* iPhone Portrait-Retina HD 5.5.png in Resources */,
0828E49A220692B500A59437 /* iPhone X_XS Portrait.png in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
0828E49E220692B500A59437 /* iPad Portrait@2x.png in Resources */,
0828E49D220692B500A59437 /* iPhone Portrait@2x.png in Resources */,
0828E499220692B500A59437 /* iPhone Portrait-Retina HD 4.7.png in Resources */,
FAD0116822F1B9DF0016E673 /* AppFrameworkInfo.plist in Resources */,
084A20882202E4FD00428FF5 /* flutter go.png in Resources */,
0828E497220692B500A59437 /* iPhone X_XS Landscape.png in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
0828E4A52206936100A59437 /* Images.xcassets in Resources */,
FAD0116922F1B9DF0016E673 /* Generated.xcconfig in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
0828E49B220692B500A59437 /* iPad Landscape@2x.png in Resources */,
0828E495220692B500A59437 /* iPhone Portrait-Retina 4.png in Resources */,
0828E498220692B500A59437 /* iPhone XS Max Portrait.png in Resources */,
<<<<<<< HEAD
=======
FAD0116422F1B9DF0016E673 /* Debug.xcconfig in Resources */,
94722E5C22511D3600F63900 /* GoogleService-Info.plist in Resources */,
>>>>>>> dxj/master
0828E496220692B500A59437 /* iPad Portrait.png in Resources */,
0828E49C220692B500A59437 /* iPhone Landscape-Retina HD 5.5.png in Resources */,
);
@ -300,24 +320,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
2432F011A7D713E4BFB3DC88 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/flutter_downloader/FlutterDownloaderDatabase.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FlutterDownloaderDatabase.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -330,29 +332,11 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
};
443E32A5789BE5CCDA6B5E59 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
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_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;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin\n";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
buildActionMask = 12;
files = (
);
inputPaths = (
@ -362,15 +346,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
};
C38E5EAE601417DA9DF11753 /* [CP] Embed Pods Frameworks */ = {
B34D03FFEA3831330E64E5C7 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
);
name = "[CP] Embed Pods Frameworks";
@ -379,7 +363,47 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
E54A6BDEF16ACE4A6988913A /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/flutter_downloader/FlutterDownloaderDatabase.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FlutterDownloaderDatabase.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
FBE7DB4E8DD084FE99B9ED05 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
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 */
@ -419,9 +443,9 @@
/* Begin XCBuildConfiguration section */
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
@ -446,7 +470,7 @@
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@ -475,9 +499,9 @@
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
@ -525,12 +549,13 @@
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
baseConfigurationReference = FAD0115E22F1B9DF0016E673 /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = Launch2;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 4WLT68XRNA;
ENABLE_BITCODE = NO;
@ -544,21 +569,24 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
ONLY_ACTIVE_ARCH = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.alibaba.fluttergo;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = FlutterGO_alibaba_distribution_app_store;
PROVISIONING_PROFILE_SPECIFIER = "";
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
baseConfigurationReference = FAD0116022F1B9DF0016E673 /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = Launch2;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 4WLT68XRNA;
ENABLE_BITCODE = NO;
@ -572,9 +600,11 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
ONLY_ACTIVE_ARCH = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.alibaba.fluttergo;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = FlutterGO_alibaba_distribution_ad_hoc;
PROVISIONING_PROFILE_SPECIFIER = "";
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
@ -589,7 +619,7 @@
97C147041CF9000F007C117D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
defaultConfigurationName = Debug;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
@ -598,7 +628,7 @@
97C147071CF9000F007C117D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
defaultConfigurationName = Debug;
};
/* End XCConfigurationList section */
};

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildSystemType</key>
<string>Original</string>
</dict>
</plist>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1000"
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -51,8 +51,7 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
@ -60,12 +59,12 @@
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
buildConfiguration = "Debug"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
@ -85,7 +84,7 @@
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
buildConfiguration = "Debug"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,5 +1,6 @@
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
#include "FlutterJPushPlugin.h"
@import Firebase;// firebase
@ -10,6 +11,8 @@
[FIRApp configure];// firebase
[self startupJPush:launchOptions appKey:@"62eb07d227d1f11dd7fa6239" channel:@"jpush" isProduction:FALSE];
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
[NSThread sleepForTimeInterval:2];

View File

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

Before

Width:  |  Height:  |  Size: 725 B

After

Width:  |  Height:  |  Size: 725 B

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -3,115 +3,115 @@
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "40*40@1x.png",
"filename" : "40x40@1x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "60*60@3x.png",
"filename" : "60x60@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "29*29@1x.png",
"filename" : "29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "58*58@2x.png",
"filename" : "58x58@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "87*87.png",
"filename" : "87x87.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "80*80@2x.png",
"filename" : "80x80@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "120*120@2x.png",
"filename" : "120x120@2x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "120*120@2x-1.png",
"filename" : "120x120@2x-1.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "180*180@3x.png",
"filename" : "180x180@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "20*20.png",
"filename" : "20x20.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "40*40@1x-2.png",
"filename" : "40x40@1x-2.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "29*29@1x-2.png",
"filename" : "29x29@1x-2.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "58*58@2x-1.png",
"filename" : "58x58@2x-1.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "40*40@1x-1.png",
"filename" : "40x40@1x-1.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "80*80@2x-1.png",
"filename" : "80x80@2x-1.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "76*76.png",
"filename" : "76x76.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "152*152.png",
"filename" : "152x152.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "167*167.png",
"filename" : "167x167.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "1024*1024@as.png",
"filename" : "1024x1024@as.png",
"scale" : "1x"
}
],

View File

@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina6_1" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
@ -14,9 +18,9 @@
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>

View File

@ -22,6 +22,8 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSApplicationCategoryType</key>
<string></string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSCameraUsageDescription</key>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist>

View File

@ -1,6 +1,6 @@
class Api{
// static const String BASE_URL = 'http://127.0.0.1:6001/';
static const String BASE_URL = 'http://flutter-go.alibaba.net/';
// static const String BASE_URL = 'http://flutter-go.alibaba.net/';
static const String BASE_URL = 'https://flutter-go.pub/api/';
static const String DO_LOGIN = BASE_URL+'doLogin';//登陆
@ -8,5 +8,29 @@ class Api{
static const String LOGOUT = BASE_URL+'logout';//退出登陆
static const String GET_USER_INFO = BASE_URL+'getUserInfo';//获取用户信息
static const String VERSION = BASE_URL+'getAppVersion';//检查版本
static const String FEEDBACK = BASE_URL+'auth/feedback';//建议反馈
// static const String LOTOUT = BASE_URL+'logout';//退出登陆
static const String GET_ALL_COLLECTION = BASE_URL+'auth/getAllUserCollection';//获取全部收藏
static const String REMOVE_COLLECTION = BASE_URL+'auth/removeCollection';//移除收藏
static const String ADD_COLLECTION = BASE_URL+'auth/addCollection';//添加收藏
static const String CHECK_COLLECTED = BASE_URL+'checkCollected';//校验收藏
static const String SET_THEMECOLOR = BASE_URL+'auth/setThemeColor';//设置主题颜色
static const String GET_THEMECOLOR = BASE_URL +'/getThemeColor';//获取主题颜色
static const String GET_WIDGET_TREE = BASE_URL + 'getCateList';//获取widget列表树
static const String SEARCH_WIDGET = BASE_URL+'searchWidget';//搜索组件
}

View File

@ -1,35 +0,0 @@
/**
* Created with Android Studio.
* User: 一晟
* Date: 2019/4/28
* Time: 3:20 PM
* email: zhu.yan@alibaba-inc.com
* tartget: FlatButton 的示例
*/
import 'dart:async';
import 'package:dio/dio.dart';
import 'dart:convert';
import './search_result.dart';
import 'package:html/parser.dart' show parse;
var dio = new Dio();
class Api {
Future<List<SearchResult>> search(name) async {
print('=========>>>');
var response = await dio.get("https://www.so.com/s?ie=utf-8&q=$name");
// var document = parse(response.data);
// var app = document.querySelectorAll('.res-title a');
List<SearchResult> res = [];
// app.forEach((f) {
// res.add(
// SearchResult(
// title: f.text,
// source: f.attributes["data-url"] ?? f.attributes["href"],
// ),
// );
// });
return res;
}
}
Api api = Api();

View File

@ -1,35 +0,0 @@
/**
* Created with Android Studio.
* User: 一晟
* Date: 2019/4/28
* Time: 7:17 PM
* email: zhu.yan@alibaba-inc.com
* tartget:
*/
import 'dart:async';
import 'package:bloc/bloc.dart';
import './search_event.dart';
import './search_state.dart';
import './search_api.dart';
/// 这里导入api类与上面的SearchEvent与SearchState文件
class SearchBloc extends Bloc<SearchEvent, SearchState> {
@override
SearchState get initialState => SearchUninitialized();
@override
Stream<SearchState> mapEventToState(SearchEvent event,) async* {
if (event is SearchFetch) {
try {
yield SearchLoading();
final res = await api.search(event.query);
yield SearchLoaded(res: res);
} catch (_) {
yield SearchError();
}
}
}
}

View File

@ -1,18 +0,0 @@
/**
* Created with Android Studio.
* User: 一晟
* Date: 2019/4/28
* Time: 7:18 PM
* email: zhu.yan@alibaba-inc.com
* tartget:
*/
abstract class SearchEvent {}
class SearchFetch extends SearchEvent {
final String query;
SearchFetch({this.query});
@override
String toString() => 'SearchFetch获取搜索结果事件';
}

View File

@ -1,14 +0,0 @@
/**
* Created with Android Studio.
* User: 一晟
* Date: 2019/4/28
* Time: 7:11 PM
* email: zhu.yan@alibaba-inc.com
* tartget:
*/
class SearchResult {
String title;
String source;
SearchResult({this.title, this.source});
}

View File

@ -1,37 +0,0 @@
/**
* Created with Android Studio.
* User: 一晟
* Date: 2019/4/28
* Time: 7:13 PM
* email: zhu.yan@alibaba-inc.com
* tartget:
*/
import './search_result.dart';
abstract class SearchState {}
class SearchError extends SearchState {
@override
String toString() => 'SearchError获取失败';
}
class SearchUninitialized extends SearchState {
@override
String toString() => 'SearchUninitialized未初始化';
}
class SearchLoading extends SearchState {
@override
String toString() => 'SearchLoading :正在加载';
}
class SearchLoaded extends SearchState {
final List<SearchResult> res;
SearchLoaded({
this.res,
});
@override
String toString() => 'SearchLoaded加载完毕';
}

View File

@ -1,80 +0,0 @@
/**
* Created with Android Studio.
* User: 一晟
* Date: 2019/4/28
* Time: 7:19 PM
* email: zhu.yan@alibaba-inc.com
* tartget:
*/
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
//import 'package:suiyi/blocs/search/bloc.dart';
import './search_event.dart';
import './search_state.dart';
import './search_bloc.dart';
class SearchWidget extends StatefulWidget {
final SearchDelegate delegate;
final String query;
SearchWidget({this.delegate, this.query});
@override
_SearchWidgetState createState() => _SearchWidgetState();
}
class _SearchWidgetState extends State<SearchWidget> {
final SearchBloc _search = SearchBloc();
String old;
@override
void dispose() {
_search.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
print('1:${old}');
print('2:${widget.query}');
if (old != widget.query) {
_search.dispatch(SearchFetch(query: widget.query));
old = widget.query;
}
return BlocBuilder(
bloc: _search,
builder: (BuildContext context, SearchState state) {
print('-------${state}');
if (state is SearchUninitialized || state is SearchLoading) {
return Center(
child: CircularProgressIndicator(),
);
} else if (state is SearchError) {
return Center(
child: Text('获取失败'),
);
} else if (state is SearchLoaded) {
return ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListTile(
dense: true,
leading: Icon(
Icons.bookmark_border,
size: 32,
),
title: Text(
state.res[index].title,
overflow: TextOverflow.ellipsis,
),
subtitle: Text(state.res[index].source),
onTap: () {
// 在这里对选中的结果进行解析因为我目前是用golang实现的所以就没贴代码了。
print(state.res[index].source);
},
);
},
itemCount: state.res.length,
);
}
},
);
}
}

View File

@ -1,16 +1,14 @@
/**
* Created with Android Studio.
* User: 一晟
* Date: 2019/4/28
* Time: 3:20 PM
* email: zhu.yan@alibaba-inc.com
* tartget: FlatButton 的示例
*/
//
// Created with Android Studio.
// User: 一晟
// Date: 2019/4/28
// Time: 3:20 PM
// email: zhu.yan@alibaba-inc.com
// tartget: FlatButton 的示例
//
import 'dart:async';
import 'package:dio/dio.dart';
import 'dart:convert';
import 'package:html/parser.dart' show parse;
import './industry_model.dart';
import './search_result.dart';
var dio = new Dio();

View File

@ -23,7 +23,7 @@ class SuggestionBloc extends Bloc<SuggestionEvent, SuggestionState> {
try {
yield SuggestionLoading();
final res = await api.suggestion(event.query);
print('res====>${res}');
// print('res====>${res}');
yield SuggestionLoaded(res: res);
} catch (_) {
yield SuggestionError();

View File

@ -1,10 +1,10 @@
/**
* Created with Android Studio.
* User: 一晟
* Date: 2019/4/28
* Time: 3:35 PM
* email: zhu.yan@alibaba-inc.com
*/
///
/// Created with Android Studio.
/// User: 一晟
/// Date: 2019/4/28
/// Time: 3:35 PM
/// email: zhu.yan@alibaba-inc.com
///
abstract class SuggestionEvent {}
class SuggestionFetch extends SuggestionEvent {

View File

@ -1,14 +1,14 @@
/**
* Created with Android Studio.
* User: 一晟
* Date: 2019/4/28
* Time: 3:52 PM
* email: zhu.yan@alibaba-inc.com
*/
///
/// Created with Android Studio.
/// User: 一晟
/// Date: 2019/4/28
/// Time: 3:52 PM
/// email: zhu.yan@alibaba-inc.com
///
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import './industry_bloc.dart';
import './industry_event.dart';
/// import './industry_event.dart';
import './industry_state.dart';
final SuggestionBloc suggestion = SuggestionBloc();
@ -22,24 +22,7 @@ class IndustryPage extends StatefulWidget {
}
class _IndustryState extends State<IndustryPage> {
@override
Widget build(BuildContext context) {
return Material(
child: Column(
children: [
// TextField(
// autofocus: true,
// textAlign: TextAlign.center,
// onSubmitted: (text) {
// print('onSubmitted:${text}');
// suggestion.dispatch(SuggestionFetch(query: text));
// },
// ),
Expanded(
child: BlocBuilder(
bloc: suggestion,
builder: (BuildContext context, SuggestionState state) {
print('BlocBuilder----${state}');
Widget renderItem(state) {
if (state is SuggestionUninitialized) {
return Center(
child: Text('暂无内容'),
@ -63,6 +46,22 @@ class _IndustryState extends State<IndustryPage> {
}
}
}
return Center(
child: Text('没有适合的结果,更换查询条件试试')
);
}
@override
Widget build(BuildContext context) {
return Material(
child: Column(
children: [
Expanded(
child: BlocBuilder(
bloc: suggestion,
builder: (BuildContext context, SuggestionState state){
/// print('BlocBuilder----${state}');
return renderItem(state);
},
),
),

View File

@ -1,10 +1,10 @@
/**
* Created with Android Studio.
* User: 一晟
* Date: 2019/4/28
* Time: 3:19 PM
* email: zhu.yan@alibaba-inc.com
*/
///
/// Created with Android Studio.
/// User: 一晟
/// Date: 2019/4/28
/// Time: 3:19 PM
/// email: zhu.yan@alibaba-inc.com
///
class Suggestion {
String query;
List<Suggestions> suggestions;

View File

@ -1,10 +1,10 @@
/**
* Created with Android Studio.
* User: 一晟
* Date: 2019/4/28
* Time: 3:37 PM
* email: zhu.yan@alibaba-inc.com
*/
///
/// Created with Android Studio.
/// User: 一晟
/// Date: 2019/4/28
/// Time: 3:37 PM
/// email: zhu.yan@alibaba-inc.com
///
abstract class SuggestionState {}
class SuggestionError extends SuggestionState {

View File

@ -1,11 +1,11 @@
/**
* Created with Android Studio.
* User: 一晟
* Date: 2019/4/28
* Time: 7:11 PM
* email: zhu.yan@alibaba-inc.com
* tartget:
*/
///
/// Created with Android Studio.
/// User: 一晟
/// Date: 2019/4/28
/// Time: 7:11 PM
/// email: zhu.yan@alibaba-inc.com
/// tartget:
///
class SearchResult {
String title;
String source;

View File

@ -1,11 +1,11 @@
import 'package:flutter/material.dart';
import '../model/cat.dart';
import '../resources/widget_name_to_icon.dart';
import '../components/widget_item_container.dart';
import '../model/widget.dart';
class CateCard extends StatefulWidget {
final Cat category;
final CategoryComponent category;
CateCard({@required this.category});
@override
_CateCardState createState() => _CateCardState();
@ -13,28 +13,15 @@ class CateCard extends StatefulWidget {
class _CateCardState extends State<CateCard> {
// 一级菜单目录下的二级Cat集合
List<Cat> _firstChildList = new List();
CatControlModel catControl = new CatControlModel();
List<CommonItem> _firstChildList;
@override
void initState() {
super.initState();
getFirstChildCategoriesByParentId();
_firstChildList = widget.category.children;
}
// 获取一层目录下的二级内容
getFirstChildCategoriesByParentId() async {
int parentId = widget.category.id;
// 构建查询条件
Cat childCateCondition = new Cat(parentId: parentId);
List<Cat> list = await catControl.getList(childCateCondition);
if (list.isNotEmpty&&list.length>=1 && this.mounted) {
setState(() {
_firstChildList = list;
});
}
}
@override
Widget build(BuildContext context) {
@ -43,7 +30,6 @@ class _CateCardState extends State<CateCard> {
//首字母转为大写
widget.category.name.substring(0, 1),
widget.category.name.substring(0, 1).toUpperCase());
return Container(
width: screenWidth,
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0),
@ -119,9 +105,8 @@ class _CateCardState extends State<CateCard> {
),
),
child: WidgetItemContainer(
categories: this._firstChildList,
columnCount: 3,
isWidgetPoint:false
commonItems: this._firstChildList,
columnCount: 3
),
);
}

View File

@ -3,16 +3,17 @@ import 'dart:async';
import 'package:flutter/material.dart';
import '../routers/application.dart';
import '../model/cat.dart';
/// import '../model/cat.dart';
import '../model/widget.dart';
import '../widgets/index.dart';
import '../components/widget_item_container.dart';
enum CateOrWigdet { Cat, WidgetDemo }
class CategoryHome extends StatefulWidget {
CategoryHome(this.name);
final String name;
CategoryHome(this.token);
final String token;
@override
_CategoryHome createState() => new _CategoryHome();
@ -21,12 +22,11 @@ class CategoryHome extends StatefulWidget {
class _CategoryHome extends State<CategoryHome> {
String title = '';
// 显示列表 cat or widget;
List<Cat> categories = [];
List<WidgetPoint> widgetPoints = [];
List<Cat> catHistory = new List();
List<CommonItem> items = [];
List<Object> widgetPoints = [];
List<CommonItem> catHistory = new List();
CatControlModel catControl = new CatControlModel();
WidgetControlModel widgetControl = new WidgetControlModel();
// 所有的可用demos;
List widgetDemosList = new WidgetDemoList().getDemos();
@ -34,80 +34,60 @@ class _CategoryHome extends State<CategoryHome> {
void initState() {
super.initState();
// 初始化加入顶级的name
this.getCatByName(widget.name).then((Cat cat) {
catHistory.add(cat);
searchCatOrWigdet();
print("这是新界面的id:>>> ${widget.token}");
CommonItem targetGroup = Application.widgetTree.find(widget.token) ?? [];
print("targetGroup::: $targetGroup");
catHistory.add(
targetGroup
);
this.setState(() {
items = targetGroup.children;
});
searchCatOrWidget();
}
Future<Cat> getCatByName(String name) async {
return await catControl.getCatByName(name);
}
Future<bool> back() {
if (catHistory.length == 1) {
// if (catHistory.length == 1) {
// return Future<bool>.value(true);
// }
// catHistory.removeLast();
// searchCatOrWidget();
return Future<bool>.value(true);
}
catHistory.removeLast();
searchCatOrWigdet();
return Future<bool>.value(false);
}
void go(Cat cat) {
void go(CommonItem cat) {
catHistory.add(cat);
searchCatOrWigdet();
searchCatOrWidget();
}
void searchCatOrWigdet() async {
void searchCatOrWidget() async {
/// CommonItem widgetTree = Application.widgetTree;
// 假设进入这个界面的parent一定存在
Cat parentCat = catHistory.last;
CommonItem targetGroup = catHistory.last;
// 继续搜索显示下一级depth: depth + 1, parentId: parentCat.id
List<Cat> _categories =
await catControl.getList(new Cat(parentId: parentCat.id));
List<WidgetPoint> _widgetPoints = new List();
if (_categories.isEmpty) {
_widgetPoints =
await widgetControl.getList(new WidgetPoint(catId: parentCat.id));
}
this.setState(() {
categories = _categories;
title = parentCat.name;
widgetPoints = _widgetPoints;
title = targetGroup.name;
});
}
void onCatgoryTap(Cat cat) {
void onCatgoryTap(CommonItem cat) {
go(cat);
}
void onWidgetTap(WidgetPoint widgetPoint) {
String targetName = widgetPoint.name;
String targetRouter = '/category/error/404';
widgetDemosList.forEach((item) {
// print("targetRouter = item.routerName> ${[item.name,targetName]}");
if (item.name == targetName) {
targetRouter = item.routerName;
}
});
Application.router.navigateTo(context, "$targetRouter");
}
Widget _buildContent() {
WidgetItemContainer wiContaienr = WidgetItemContainer(
columnCount: 3,
categories: categories,
isWidgetPoint:false
commonItems: items
);
if (widgetPoints.length > 0) {
wiContaienr = WidgetItemContainer(
categories: widgetPoints,
columnCount: 3,
isWidgetPoint:true
);
}
return Container(
padding: const EdgeInsets.only(bottom: 10.0, top: 5.0),
decoration: BoxDecoration(
@ -122,14 +102,18 @@ class _CategoryHome extends State<CategoryHome> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
title: Text("$title"),
),
body: WillPopScope(
onWillPop: () {
return back();
},
child: ListView(
children: <Widget>[
_buildContent(),

View File

@ -9,7 +9,6 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
const disclaimerText1 =
'\r\r\r\r\r\r本APP属于个人的非赢利性开源项目以供开源社区使用凡本APP转载的所有的文章 、图片、音频、视频文件等资料的版权归版权所有人所有本APP采用的非本站原创文章及图片等内容无法一一和版权者联系如果本网所选内容的文章作者及编辑认为其作品不宜上网供大家浏览或不应无偿使用请及时用电子邮件或电话通知我们以迅速采取适当措施避免给双方造成不必要的经济损失。';
const disclaimerText2 =
@ -23,6 +22,7 @@ class DisclaimerMsg extends StatefulWidget {
DisclaimerMsgState createState() => DisclaimerMsgState();
}
class DisclaimerMsgState extends State<DisclaimerMsg> {
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
Future<bool> _unKnow;
@ -33,9 +33,12 @@ class DisclaimerMsgState extends State<DisclaimerMsg> {
void refs(bool value) async {
final SharedPreferences prefs = await _prefs;
final bool unKnow = value;
_valBool = value;
_readed = value;
if (mounted) {
setState(() {
_unKnow = prefs.setBool("disclaimer::Boolean", unKnow).then((bool success) {
_unKnow =
prefs.setBool("disclaimer::Boolean", unKnow).then((bool success) {
return unKnow;
});
});
@ -60,111 +63,15 @@ class DisclaimerMsgState extends State<DisclaimerMsg> {
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
//title: Text('免责声明'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(5.0, 5.0, 10.0, 10.0),
//width: 100,
height: 35,
child: Text('免责声明',
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.w700)),
decoration: BoxDecoration(
//color: Colors.blue,
image: DecorationImage(
fit: BoxFit.fitWidth,
image: AssetImage('assets/images/paimaiLogo.png')),
borderRadius: BorderRadius.all(
Radius.circular(10.0),
),
//alignment: Alignment.bottomRight,
)),
SizedBox(height: 20),
Text(disclaimerText1),
Text(disclaimerText2),
],
),
),
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(20.0)), // 圆角
actions: <Widget>[
new Container(
width: 250,
child: _create(),
)
],
);
},
);
}
Row _create() {
//已读
if (_readed) {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FlatButton(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: Text('已阅读知晓',
style: TextStyle(fontSize: 16, color: Colors.white)),
//可点击
color: Theme.of(context).primaryColor,
onPressed: () {
Navigator.of(context).pop();
},
),
SizedBox(
width: 10.0,
)
],
);
}
//第一次读取
return Row(mainAxisAlignment: MainAxisAlignment.spaceAround,
//crossAxisAlignment:CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Checkbox(
activeColor: Theme.of(context).primaryColor,
tristate: false,
value: _valBool,
onChanged: (bool bol) {
if(mounted) {
setState(() {
_valBool = bol;
return DisclaimerMsgDialog(_valBool, _readed, (b){
refs(b);
});
}
Navigator.of(context).pop(); // here I pop to avoid multiple Dialogs
showAlertDialog(context); //here i call the same function
}),
Text('不再自动提示', style: TextStyle(fontSize: 14)),
],
),
FlatButton(
child: Text('知道了',
style: TextStyle(fontSize: 16, color: Colors.white)),
//可点击
color: _valBool
? Theme.of(context).primaryColor
: Theme.of(context).primaryColor.withAlpha(800),
onPressed: () {
// if (_valBool) {
refs(_valBool);
Navigator.of(context).pop();
// }
},
),
]);
);
}
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
@ -194,3 +101,150 @@ class DisclaimerMsgState extends State<DisclaimerMsg> {
));
}
}
class DisclaimerMsgDialog extends StatefulWidget {
final bool valBool;
final bool readed;
final ValueChanged<bool> onValueChanged;
DisclaimerMsgDialog(this.valBool, this.readed, this.onValueChanged);
@override
_DisclaimerMsgDialogState createState() => _DisclaimerMsgDialogState();
}
class _DisclaimerMsgDialogState extends State<DisclaimerMsgDialog> {
bool readBool;
@override
void initState() {
super.initState();
readBool = widget.valBool;
}
Row _create() {
//已读
if (widget.readed) {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FlatButton(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: Text('已阅读知晓',
style: TextStyle(fontSize: 16, color: Colors.white)),
//可点击
color: Theme
.of(context)
.primaryColor,
onPressed: () {
Navigator.of(context).pop();
},
),
SizedBox(
width: 10.0,
)
],
);
}
/// 选中状态更新,并返回数据
checkChanged(){
if (mounted) {
setState(() {
readBool = !readBool;
});
}
}
//第一次读取
return Row(mainAxisAlignment: MainAxisAlignment.spaceAround,
//crossAxisAlignment:CrossAxisAlignment.start,
children: <Widget>[
GestureDetector(
onTap: (){
checkChanged();
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Checkbox(
activeColor: Theme
.of(context)
.primaryColor,
tristate: false,
value: readBool,
onChanged: (bool bol) {
checkChanged();
}),
Text('不再自动提示', style: TextStyle(fontSize: 14)),
],
),
),
FlatButton(
child: Text('知道了',
style: TextStyle(fontSize: 16, color: Colors.white)),
//可点击
color: readBool
? Theme
.of(context)
.primaryColor
: Theme
.of(context)
.primaryColor
.withAlpha(800),
onPressed: () {
widget.onValueChanged(readBool);
Navigator.of(context).pop();
},
),
]);
}
@override
Widget build(BuildContext context) {
return AlertDialog(
//title: Text('免责声明'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(5.0, 5.0, 10.0, 10.0),
//width: 100,
height: 35,
child: Text('免责声明',
style:
TextStyle(fontSize: 18, fontWeight: FontWeight.w700)),
decoration: BoxDecoration(
//color: Colors.blue,
image: DecorationImage(
fit: BoxFit.fitWidth,
image: AssetImage('assets/images/paimaiLogo.png')),
borderRadius: BorderRadius.all(
Radius.circular(10.0),
),
//alignment: Alignment.bottomRight,
)),
SizedBox(height: 20),
Text(disclaimerText1),
Text(disclaimerText2),
],
),
),
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(20.0)), // 圆角
actions: <Widget>[
new Container(
width: 250,
child: _create(),
)
],
);
}}

View File

@ -0,0 +1,27 @@
// Copyright 2017 Google, Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,39 @@
# Flutter Markdown
[![pub package](https://img.shields.io/pub/v/flutter_markdown.svg)](https://pub.dartlang.org/packages/flutter_markdown)
[![Build Status](https://travis-ci.org/flutter/flutter_markdown.svg?branch=master)](https://travis-ci.org/flutter/flutter_markdown)
A markdown renderer for Flutter. It supports the
[original format](https://daringfireball.net/projects/markdown/), but no inline
html.
## Getting Started
Using the Markdown widget is simple, just pass in the source markdown as a
string:
new Markdown(data: markdownSource);
If you do not want the padding or scrolling behavior, use the MarkdownBody
instead:
new MarkdownBody(data: markdownSource);
By default, Markdown uses the formatting from the current material design theme,
but it's possible to create your own custom styling. Use the MarkdownStyle class
to pass in your own style. If you don't want to use Markdown outside of material
design, use the MarkdownRaw class.
## Image support
The `Img` tag only supports the following image locations:
* From the network: Use a URL prefixed by either `http://` or `https://`.
* From local files on the device: Use an absolute path to the file, for example by
concatenating the file name with the path returned by a known storage location,
such as those provided by the [`path_provider`](https://pub.dartlang.org/packages/path_provider)
plugin.
* From image locations referring to bundled assets: Use an asset name prefixed by `resource:`.
like `resource:assets/image.png`.

View File

@ -0,0 +1,10 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// A library to render markdown formatted text.
library flutter_markdown;
export 'src/builder.dart';
export 'src/style_sheet.dart';
export 'src/widget.dart';

View File

@ -0,0 +1,376 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart';
import 'package:markdown/markdown.dart' as md;
import 'package:path/path.dart' as p;
import 'style_sheet.dart';
typedef Widget DemoBuilder(Map<String, dynamic> attrs);
final Set<String> _kBlockTags = new Set<String>.from(<String>[
'p',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'li',
'blockquote',
'pre',
'ol',
'ul',
'hr',
]);
const List<String> _kListTags = const <String>['ul', 'ol'];
bool _isBlockTag(String tag) => _kBlockTags.contains(tag);
bool _isListTag(String tag) => _kListTags.contains(tag);
class _BlockElement {
_BlockElement(this.tag);
final String tag;
final List<Widget> children = <Widget>[];
int nextListIndex = 0;
}
/// A collection of widgets that should be placed adjacent to (inline with)
/// other inline elements in the same parent block.
///
/// Inline elements can be textual (a/em/strong) represented by [RichText]
/// widgets or images (img) represented by [Image.network] widgets.
///
/// Inline elements can be nested within other inline elements, inheriting their
/// parent's style along with the style of the block they are in.
///
/// When laying out inline widgets, first, any adjacent RichText widgets are
/// merged, then, all inline widgets are enclosed in a parent [Wrap] widget.
class _InlineElement {
_InlineElement(this.tag, {this.style});
final String tag;
/// Created by merging the style defined for this element's [tag] in the
/// delegate's [MarkdownStyleSheet] with the style of its parent.
final TextStyle style;
final List<Widget> children = <Widget>[];
}
/// A delegate used by [MarkdownBuilder] to control the widgets it creates.
abstract class MarkdownBuilderDelegate {
/// Returns a gesture recognizer to use for an `a` element with the given
/// `href` attribute.
GestureRecognizer createLink(String href);
/// Returns formatted text to use to display the given contents of a `pre`
/// element.
///
/// The `styleSheet` is the value of [MarkdownBuilder.styleSheet].
TextSpan formatText(MarkdownStyleSheet styleSheet, String code);
}
/// Builds a [Widget] tree from parsed Markdown.
///
/// See also:
///
/// * [Markdown], which is a widget that parses and displays Markdown.
class MarkdownBuilder implements md.NodeVisitor {
/// Creates an object that builds a [Widget] tree from parsed Markdown.
MarkdownBuilder({
this.delegate,
this.styleSheet,
this.imageDirectory,
this.demoParser
});
/// A delegate that controls how link and `pre` elements behave.
final MarkdownBuilderDelegate delegate;
/// Defines which [TextStyle] objects to use for each type of element.
final MarkdownStyleSheet styleSheet;
final DemoBuilder demoParser;
/// The base directory holding images referenced by Img tags with local file paths.
final Directory imageDirectory;
final List<String> _listIndents = <String>[];
final List<_BlockElement> _blocks = <_BlockElement>[];
final List<_InlineElement> _inlines = <_InlineElement>[];
final List<GestureRecognizer> _linkHandlers = <GestureRecognizer>[];
/// Returns widgets that display the given Markdown nodes.
///
/// The returned widgets are typically used as children in a [ListView].
List<Widget> build(List<md.Node> nodes) {
_listIndents.clear();
_blocks.clear();
_inlines.clear();
_linkHandlers.clear();
_blocks.add(new _BlockElement(null));
for (md.Node node in nodes) {
assert(_blocks.length == 1);
node.accept(this);
}
assert(_inlines.isEmpty);
return _blocks.single.children;
}
@override
void visitText(md.Text text) {
if (_blocks.last.tag == null) // Don't allow text directly under the root.
return;
_addParentInlineIfNeeded(_blocks.last.tag);
final TextSpan span = _blocks.last.tag == 'pre'
? delegate.formatText(styleSheet, text.text)
: new TextSpan(
style: _inlines.last.style,
text: text.text,
recognizer: _linkHandlers.isNotEmpty ? _linkHandlers.last : null,
);
_inlines.last.children.add(new RichText(
textScaleFactor: styleSheet.textScaleFactor,
text: span,
));
}
@override
bool visitElementBefore(md.Element element) {
// print("visitElementBefore ${element.tag}");
final String tag = element.tag;
if (_isBlockTag(tag)) {
_addAnonymousBlockIfNeeded(styleSheet.styles[tag]);
if (_isListTag(tag))
_listIndents.add(tag);
_blocks.add(new _BlockElement(tag));
} else {
_addParentInlineIfNeeded(_blocks.last.tag);
TextStyle parentStyle = _inlines.last.style;
_inlines.add(new _InlineElement(
tag,
style: parentStyle.merge(styleSheet.styles[tag]),
));
}
if (tag == 'a') {
_linkHandlers.add(delegate.createLink(element.attributes['href']));
}
return true;
}
@override
void visitElementAfter(md.Element element) {
final String tag = element.tag;
if (_isBlockTag(tag)) {
_addAnonymousBlockIfNeeded(styleSheet.styles[tag]);
final _BlockElement current = _blocks.removeLast();
Widget child;
if (current.children.isNotEmpty) {
child = new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: current.children,
);
} else {
child = const SizedBox();
}
if (_isListTag(tag)) {
assert(_listIndents.isNotEmpty);
_listIndents.removeLast();
} else if (tag == 'li') {
if (_listIndents.isNotEmpty) {
child = new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new SizedBox(
width: styleSheet.listIndent,
child: _buildBullet(_listIndents.last),
),
new Expanded(child: child)
],
);
}
} else if (tag == 'blockquote') {
child = new DecoratedBox(
decoration: styleSheet.blockquoteDecoration,
child: new Padding(
padding: new EdgeInsets.all(styleSheet.blockquotePadding),
child: child,
),
);
} else if (tag == 'pre') {
child = new DecoratedBox(
decoration: styleSheet.codeblockDecoration,
child: new Padding(
padding: new EdgeInsets.all(styleSheet.codeblockPadding),
child: child,
),
);
} else if (tag == 'hr') {
child = new DecoratedBox(
decoration: styleSheet.horizontalRuleDecoration,
child: child,
);
}
_addBlockChild(child);
} else {
final _InlineElement current = _inlines.removeLast();
final _InlineElement parent = _inlines.last;
if (tag == 'img') {
// create an image widget for this image
current.children.add(_buildImage(element.attributes['src']));
} else if (tag == 'a') {
_linkHandlers.removeLast();
} else if (tag == 'demo') {
current.children.add(_buildGoDemos(element.attributes));
}
if (current.children.isNotEmpty) {
parent.children.addAll(current.children);
}
}
}
Widget _buildGoDemos(Map<String, dynamic> attrs) {
Widget targetGoDemos;
if (demoParser != null) {
targetGoDemos = demoParser(attrs);
}
return targetGoDemos ?? new Text('demo not exits');
}
Widget _buildImage(String src) {
final List<String> parts = src.split('#');
if (parts.isEmpty)
return const SizedBox();
final String path = parts.first;
double width;
double height;
if (parts.length == 2) {
final List<String> dimensions = parts.last.split('x');
if (dimensions.length == 2) {
width = double.parse(dimensions[0]);
height = double.parse(dimensions[1]);
}
}
Uri uri = Uri.parse(path);
Widget child;
if (uri.scheme == 'http' || uri.scheme == 'https') {
child = new Image.network(uri.toString(), width: width, height: height);
} else if (uri.scheme == 'data') {
child = _handleDataSchemeUri(uri, width, height);
} else if (uri.scheme == "resource") {
child = new Image.asset(path.substring(9), width: width, height: height);
} else {
String filePath = (imageDirectory == null
? uri.toFilePath()
: p.join(imageDirectory.path, uri.toFilePath()));
child = new Image.file(new File(filePath), width: width, height: height);
}
if (_linkHandlers.isNotEmpty) {
TapGestureRecognizer recognizer = _linkHandlers.last;
return new GestureDetector(child: child, onTap: recognizer.onTap);
} else {
return child;
}
}
Widget _handleDataSchemeUri(Uri uri, final double width, final double height) {
final String mimeType = uri.data.mimeType;
if (mimeType.startsWith('image/')) {
return new Image.memory(uri.data.contentAsBytes(), width: width, height: height);
} else if (mimeType.startsWith('text/')) {
return new Text(uri.data.contentAsString());
}
return const SizedBox();
}
Widget _buildBullet(String listTag) {
if (listTag == 'ul')
return new Text('', textAlign: TextAlign.center, style: styleSheet.styles['li']);
final int index = _blocks.last.nextListIndex;
return new Padding(
padding: const EdgeInsets.only(right: 5.0),
child: new Text('${index + 1}.', textAlign: TextAlign.right, style: styleSheet.styles['li']),
);
}
void _addParentInlineIfNeeded(String tag) {
if (_inlines.isEmpty) {
_inlines.add(new _InlineElement(
tag,
style: styleSheet.styles[tag],
));
}
}
void _addBlockChild(Widget child) {
final _BlockElement parent = _blocks.last;
if (parent.children.isNotEmpty)
parent.children.add(new SizedBox(height: styleSheet.blockSpacing));
parent.children.add(child);
parent.nextListIndex += 1;
}
void _addAnonymousBlockIfNeeded(TextStyle style) {
if (_inlines.isEmpty) {
return;
}
final _InlineElement inline = _inlines.single;
if (inline.children.isNotEmpty) {
List<Widget> mergedInlines = _mergeInlineChildren(inline);
final Wrap wrap = new Wrap(children: mergedInlines);
_addBlockChild(wrap);
_inlines.clear();
}
}
/// Merges adjacent [TextSpan] children of the given [_InlineElement]
List<Widget> _mergeInlineChildren(_InlineElement inline) {
List<Widget> mergedTexts = <Widget>[];
for (Widget child in inline.children) {
if (mergedTexts.isNotEmpty && mergedTexts.last is RichText && child is RichText) {
RichText previous = mergedTexts.removeLast();
List<TextSpan> children = previous.text.children != null
? new List.from(previous.text.children)
: [previous.text];
children.add(child.text);
TextSpan mergedSpan = new TextSpan(children: children);
mergedTexts.add(new RichText(
textScaleFactor: styleSheet.textScaleFactor,
text: mergedSpan,
));
} else {
mergedTexts.add(child);
}
}
return mergedTexts;
}
}

View File

@ -0,0 +1,307 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
/// Defines which [TextStyle] objects to use for which Markdown elements.
class MarkdownStyleSheet {
/// Creates an explicit mapping of [TextStyle] objects to Markdown elements.
MarkdownStyleSheet({
this.a,
this.p,
this.code,
this.h1,
this.h2,
this.h3,
this.h4,
this.h5,
this.h6,
this.em,
this.strong,
this.blockquote,
this.img,
this.blockSpacing,
this.listIndent,
this.blockquotePadding,
this.blockquoteDecoration,
this.codeblockPadding,
this.codeblockDecoration,
this.horizontalRuleDecoration,
this.textScaleFactor = 1.0
}) : _styles = <String, TextStyle>{
'a': a,
'p': p,
'li': p,
'code': code,
'pre': p,
'h1': h1,
'h2': h2,
'h3': h3,
'h4': h4,
'h5': h5,
'h6': h6,
'em': em,
'strong': strong,
'blockquote': blockquote,
'img': img,
};
/// Creates a [MarkdownStyleSheet] from the [TextStyle]s in the provided [ThemeData].
factory MarkdownStyleSheet.fromTheme(ThemeData theme) {
assert(theme?.textTheme?.body1?.fontSize != null);
return new MarkdownStyleSheet(
a: const TextStyle(color: Colors.blue),
p: theme.textTheme.body1,
code: new TextStyle(
color: Colors.grey.shade700,
fontFamily: "monospace",
fontSize: theme.textTheme.body1.fontSize * 0.85
),
h1: theme.textTheme.headline,
h2: theme.textTheme.title,
h3: theme.textTheme.subhead,
h4: theme.textTheme.body2,
h5: theme.textTheme.body2,
h6: theme.textTheme.body2,
em: const TextStyle(fontStyle: FontStyle.italic),
strong: const TextStyle(fontWeight: FontWeight.bold),
blockquote: theme.textTheme.body1,
img: theme.textTheme.body1,
blockSpacing: 8.0,
listIndent: 32.0,
blockquotePadding: 8.0,
blockquoteDecoration: new BoxDecoration(
color: Colors.blue.shade100,
borderRadius: new BorderRadius.circular(2.0)
),
codeblockPadding: 8.0,
codeblockDecoration: new BoxDecoration(
color: Colors.grey.shade100,
borderRadius: new BorderRadius.circular(2.0)
),
horizontalRuleDecoration: new BoxDecoration(
border: new Border(
top: new BorderSide(width: 5.0, color: Colors.grey.shade300)
),
),
);
}
/// Creates a [MarkdownStyle] from the [TextStyle]s in the provided [ThemeData].
///
/// This constructor uses larger fonts for the headings than in
/// [MarkdownStyle.fromTheme].
factory MarkdownStyleSheet.largeFromTheme(ThemeData theme) {
return new MarkdownStyleSheet(
a: const TextStyle(color: Colors.blue),
p: theme.textTheme.body1,
code: new TextStyle(
color: Colors.grey.shade700,
fontFamily: "monospace",
fontSize: theme.textTheme.body1.fontSize * 0.85
),
h1: theme.textTheme.display3,
h2: theme.textTheme.display2,
h3: theme.textTheme.display1,
h4: theme.textTheme.headline,
h5: theme.textTheme.title,
h6: theme.textTheme.subhead,
em: const TextStyle(fontStyle: FontStyle.italic),
strong: const TextStyle(fontWeight: FontWeight.bold),
blockquote: theme.textTheme.body1,
img: theme.textTheme.body1,
blockSpacing: 8.0,
listIndent: 32.0,
blockquotePadding: 8.0,
blockquoteDecoration: new BoxDecoration(
color: Colors.blue.shade100,
borderRadius: new BorderRadius.circular(2.0)
),
codeblockPadding: 8.0,
codeblockDecoration: new BoxDecoration(
color: Colors.grey.shade100,
borderRadius: new BorderRadius.circular(2.0)
),
horizontalRuleDecoration: new BoxDecoration(
border: new Border(
top: new BorderSide(width: 5.0, color: Colors.grey.shade300)
),
),
);
}
/// Creates a new [MarkdownStyleSheet] based on the current style, with the
/// provided parameters overridden.
MarkdownStyleSheet copyWith({
TextStyle a,
TextStyle p,
TextStyle code,
TextStyle h1,
TextStyle h2,
TextStyle h3,
TextStyle h4,
TextStyle h5,
TextStyle h6,
TextStyle em,
TextStyle strong,
TextStyle blockquote,
TextStyle img,
double blockSpacing,
double listIndent,
double blockquotePadding,
Decoration blockquoteDecoration,
double codeblockPadding,
Decoration codeblockDecoration,
Decoration horizontalRuleDecoration,
double textScaleFactor,
}) {
return new MarkdownStyleSheet(
a: a ?? this.a,
p: p ?? this.p,
code: code ?? this.code,
h1: h1 ?? this.h1,
h2: h2 ?? this.h2,
h3: h3 ?? this.h3,
h4: h4 ?? this.h4,
h5: h5 ?? this.h5,
h6: h6 ?? this.h6,
em: em ?? this.em,
strong: strong ?? this.strong,
blockquote: blockquote ?? this.blockquote,
img: img ?? this.img,
blockSpacing: blockSpacing ?? this.blockSpacing,
listIndent: listIndent ?? this.listIndent,
blockquotePadding: blockquotePadding ?? this.blockquotePadding,
blockquoteDecoration: blockquoteDecoration ?? this.blockquoteDecoration,
codeblockPadding: codeblockPadding ?? this.codeblockPadding,
codeblockDecoration: codeblockDecoration ?? this.codeblockDecoration,
horizontalRuleDecoration: horizontalRuleDecoration ?? this.horizontalRuleDecoration,
textScaleFactor : textScaleFactor ?? this.textScaleFactor,
);
}
/// The [TextStyle] to use for `a` elements.
final TextStyle a;
/// The [TextStyle] to use for `p` elements.
final TextStyle p;
/// The [TextStyle] to use for `code` elements.
final TextStyle code;
/// The [TextStyle] to use for `h1` elements.
final TextStyle h1;
/// The [TextStyle] to use for `h2` elements.
final TextStyle h2;
/// The [TextStyle] to use for `h3` elements.
final TextStyle h3;
/// The [TextStyle] to use for `h4` elements.
final TextStyle h4;
/// The [TextStyle] to use for `h5` elements.
final TextStyle h5;
/// The [TextStyle] to use for `h6` elements.
final TextStyle h6;
/// The [TextStyle] to use for `em` elements.
final TextStyle em;
/// The [TextStyle] to use for `strong` elements.
final TextStyle strong;
/// The [TextStyle] to use for `blockquote` elements.
final TextStyle blockquote;
/// The [TextStyle] to use for `img` elements.
final TextStyle img;
/// The amount of vertical space to use between block-level elements.
final double blockSpacing;
/// The amount of horizontal space to indent list items.
final double listIndent;
/// The padding to use for `blockquote` elements.
final double blockquotePadding;
/// The decoration to use behind `blockquote` elements.
final Decoration blockquoteDecoration;
/// The padding to use for `pre` elements.
final double codeblockPadding;
/// The decoration to use behind for `pre` elements.
final Decoration codeblockDecoration;
/// The decoration to use for `hr` elements.
final Decoration horizontalRuleDecoration;
// The text scale factor to use in textual elements
final double textScaleFactor;
/// A [Map] from element name to the corresponding [TextStyle] object.
Map<String, TextStyle> get styles => _styles;
Map<String, TextStyle> _styles;
@override
bool operator ==(dynamic other) {
if (identical(this, other))
return true;
if (other.runtimeType != MarkdownStyleSheet)
return false;
final MarkdownStyleSheet typedOther = other;
return typedOther.a == a
&& typedOther.p == p
&& typedOther.code == code
&& typedOther.h1 == h1
&& typedOther.h2 == h2
&& typedOther.h3 == h3
&& typedOther.h4 == h4
&& typedOther.h5 == h5
&& typedOther.h6 == h6
&& typedOther.em == em
&& typedOther.strong == strong
&& typedOther.blockquote == blockquote
&& typedOther.img == img
&& typedOther.blockSpacing == blockSpacing
&& typedOther.listIndent == listIndent
&& typedOther.blockquotePadding == blockquotePadding
&& typedOther.blockquoteDecoration == blockquoteDecoration
&& typedOther.codeblockPadding == codeblockPadding
&& typedOther.codeblockDecoration == codeblockDecoration
&& typedOther.horizontalRuleDecoration == horizontalRuleDecoration
&& typedOther.textScaleFactor == textScaleFactor;
}
@override
int get hashCode {
return hashList([
a,
p,
code,
h1,
h2,
h3,
h4,
h5,
h6,
em,
strong,
blockquote,
img,
blockSpacing,
listIndent,
blockquotePadding,
blockquoteDecoration,
codeblockPadding,
codeblockDecoration,
horizontalRuleDecoration,
textScaleFactor,
]);
}
}

View File

@ -0,0 +1,247 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:markdown/markdown.dart' as md;
import 'package:meta/meta.dart';
import 'builder.dart';
import 'style_sheet.dart';
//
typedef Widget ItemDemoBuilder(Map<String, dynamic> attrs);
/// Signature for callbacks used by [MarkdownWidget] when the user taps a link.
///
/// Used by [MarkdownWidget.onTapLink].
typedef void MarkdownTapLinkCallback(String href);
/// Creates a format [TextSpan] given a string.
///
/// Used by [MarkdownWidget] to highlight the contents of `pre` elements.
abstract class SyntaxHighlighter { // ignore: one_member_abstracts
/// Returns the formated [TextSpan] for the given string.
TextSpan format(String source);
}
/// A base class for widgets that parse and display Markdown.
///
/// Supports all standard Markdown from the original
/// [Markdown specification](https://daringfireball.net/projects/markdown/).
///
/// See also:
///
/// * [Markdown], which is a scrolling container of Markdown.
/// * [MarkdownBody], which is a non-scrolling container of Markdown.
/// * <https://daringfireball.net/projects/markdown/>
abstract class MarkdownWidget extends StatefulWidget {
/// Creates a widget that parses and displays Markdown.
///
/// The [data] argument must not be null.
const MarkdownWidget({
Key key,
@required this.data,
this.styleSheet,
this.syntaxHighlighter,
this.onTapLink,
this.imageDirectory,
this.demoBuilder,
}) : assert(data != null),
super(key: key);
/// The Markdown to display.
final String data;
/// The styles to use when displaying the Markdown.
///
/// If null, the styles are inferred from the current [Theme].
final MarkdownStyleSheet styleSheet;
/// The syntax highlighter used to color text in `pre` elements.
///
/// If null, the [MarkdownStyleSheet.code] style is used for `pre` elements.
final SyntaxHighlighter syntaxHighlighter;
/// Called when the user taps a link.
final MarkdownTapLinkCallback onTapLink;
/// The base directory holding images referenced by Img tags with local file paths.
final Directory imageDirectory;
final ItemDemoBuilder demoBuilder;
/// Subclasses should override this function to display the given children,
/// which are the parsed representation of [data].
@protected
Widget build(BuildContext context, List<Widget> children);
@override
_MarkdownWidgetState createState() => new _MarkdownWidgetState();
}
class DemosSyntax extends md.InlineSyntax {
DemosSyntax() : super('\\[demo:([a-z0-9_+-]+)\\]');
bool onMatch(parser, match) {
var anchor = new md.Element.empty('demo');
anchor.attributes['id'] = match[1];
parser.addNode(anchor);
return true;
}
}
class _MarkdownWidgetState extends State<MarkdownWidget> implements MarkdownBuilderDelegate {
List<Widget> _children;
final List<GestureRecognizer> _recognizers = <GestureRecognizer>[];
@override
void didChangeDependencies() {
_parseMarkdown();
super.didChangeDependencies();
}
@override
void didUpdateWidget(MarkdownWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.data != oldWidget.data
|| widget.styleSheet != oldWidget.styleSheet)
_parseMarkdown();
}
@override
void dispose() {
_disposeRecognizers();
super.dispose();
}
void _parseMarkdown() {
final MarkdownStyleSheet styleSheet = widget.styleSheet ?? new MarkdownStyleSheet.fromTheme(Theme.of(context));
_disposeRecognizers();
// TODO: This can be optimized by doing the split and removing \r at the same time
final List<String> lines = widget.data.replaceAll('\r\n', '\n').split('\n');
final md.ExtensionSet extens = new md.ExtensionSet([
md.FencedCodeBlockSyntax()
], [
new DemosSyntax(),
new md.InlineHtmlSyntax(),
]);
final md.Document document = new md.Document(encodeHtml: false, extensionSet: extens);
final MarkdownBuilder builder = new MarkdownBuilder(
delegate: this,
styleSheet: styleSheet,
imageDirectory: widget.imageDirectory,
demoParser: widget.demoBuilder
);
_children = builder.build(document.parseLines(lines));
}
void _disposeRecognizers() {
if (_recognizers.isEmpty)
return;
final List<GestureRecognizer> localRecognizers = new List<GestureRecognizer>.from(_recognizers);
_recognizers.clear();
for (GestureRecognizer recognizer in localRecognizers)
recognizer.dispose();
}
@override
GestureRecognizer createLink(String href) {
final TapGestureRecognizer recognizer = new TapGestureRecognizer()
..onTap = () {
if (widget.onTapLink != null)
widget.onTapLink(href);
};
_recognizers.add(recognizer);
return recognizer;
}
@override
TextSpan formatText(MarkdownStyleSheet styleSheet, String code) {
if (widget.syntaxHighlighter != null)
return widget.syntaxHighlighter.format(code);
return new TextSpan(style: styleSheet.code, text: code);
}
@override
Widget build(BuildContext context) => widget.build(context, _children);
}
/// A non-scrolling widget that parses and displays Markdown.
///
/// Supports all standard Markdown from the original
/// [Markdown specification](https://daringfireball.net/projects/markdown/).
///
/// See also:
///
/// * [Markdown], which is a scrolling container of Markdown.
/// * <https://daringfireball.net/projects/markdown/>
class MarkdownBody extends MarkdownWidget {
/// Creates a non-scrolling widget that parses and displays Markdown.
const MarkdownBody({
Key key,
String data,
MarkdownStyleSheet styleSheet,
SyntaxHighlighter syntaxHighlighter,
MarkdownTapLinkCallback onTapLink,
Directory imageDirectory,
ItemDemoBuilder demoBuilder,
}) : super(
key: key,
data: data,
styleSheet: styleSheet,
syntaxHighlighter: syntaxHighlighter,
onTapLink: onTapLink,
imageDirectory: imageDirectory,
demoBuilder: demoBuilder
);
@override
Widget build(BuildContext context, List<Widget> children) {
if (children.length == 1)
return children.single;
return new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: children,
);
}
}
/// A scrolling widget that parses and displays Markdown.
///
/// Supports all standard Markdown from the original
/// [Markdown specification](https://daringfireball.net/projects/markdown/).
///
/// See also:
///
/// * [MarkdownBody], which is a non-scrolling container of Markdown.
/// * <https://daringfireball.net/projects/markdown/>
class Markdown extends MarkdownWidget {
/// Creates a scrolling widget that parses and displays Markdown.
const Markdown({
Key key,
String data,
MarkdownStyleSheet styleSheet,
SyntaxHighlighter syntaxHighlighter,
MarkdownTapLinkCallback onTapLink,
Directory imageDirectory,
this.padding: const EdgeInsets.all(16.0),
}) : super(
key: key,
data: data,
styleSheet: styleSheet,
syntaxHighlighter: syntaxHighlighter,
onTapLink: onTapLink,
imageDirectory: imageDirectory,
);
/// The amount of space by which to inset the children.
final EdgeInsets padding;
@override
Widget build(BuildContext context, List<Widget> children) {
return new ListView(padding: padding, children: children);
}
}

View File

@ -7,11 +7,13 @@ import 'package:flutter/material.dart';
import 'package:flutter_go/utils/example_code_parser.dart';
import 'package:flutter_go/utils/syntax_highlighter.dart';
import 'package:flutter_go/utils/net_utils.dart';
class FullScreenCodeDialog extends StatefulWidget {
const FullScreenCodeDialog({this.filePath});
const FullScreenCodeDialog({this.filePath, this.remoteFilePath});
final String filePath;
final String remoteFilePath;
_FullScreenCodeDialogState createState() => _FullScreenCodeDialogState();
}
@ -21,6 +23,7 @@ class _FullScreenCodeDialogState extends State<FullScreenCodeDialog> {
@override
void didChangeDependencies() {
print('widget.filePath=======${widget.filePath}');
if (widget.filePath != null) {
getExampleCode(context,'${widget.filePath}', DefaultAssetBundle.of(context))
.then<void>((String code) {
if (mounted) {
@ -29,9 +32,22 @@ class _FullScreenCodeDialogState extends State<FullScreenCodeDialog> {
});
}
});
}
if (widget.remoteFilePath != null) {
getRemotePathCode(widget.remoteFilePath);
}
super.didChangeDependencies();
}
getRemotePathCode(path) async {
String response = await NetUtils.get(path);
if (mounted) {
setState(() {
_exampleCode = response ?? 'Example code not found';
});
}
}
@override
Widget build(BuildContext context) {
final SyntaxHighlighterStyle style =

View File

@ -174,6 +174,7 @@ class _ListRefreshState extends State<ListRefresh> {
return widget.renderItem(index, items[index]);
}
}
return null;
},
controller: _scrollController,
),

View File

@ -0,0 +1,94 @@
//
// Created with Android Studio.
// User: 三帆
// Date: 07/08/2019
// Time: 08:40
// email: sanfan.hx@alibaba-inc.com
// tartget: 代码获取自: https://blog.csdn.net/O_time/article/details/86496537
//
import 'dart:async';
import 'package:flutter/material.dart';
// ignore: must_be_immutable
class NetLoadingDialog extends StatefulWidget {
String loadingText;
bool outsideDismiss;
bool loading;
Function dismissCallback;
Future<dynamic> requestCallBack;
NetLoadingDialog(
{Key key,
this.loadingText = "loading...",
this.outsideDismiss = true,
this.dismissCallback,
this.loading,
this.requestCallBack})
: super(key: key);
@override
State<NetLoadingDialog> createState() => _LoadingDialog();
}
class _LoadingDialog extends State<NetLoadingDialog> {
_dismissDialog() {
if (widget.dismissCallback != null) {
widget.dismissCallback();
}
Navigator.of(context).pop();
}
@override
void initState() {
super.initState();
if (widget.requestCallBack != null) {
widget.requestCallBack.then((_) {
Navigator.pop(context);
});
}
}
@override
Widget build(BuildContext context) {
if (!widget.loading) {
return Container();
}
return new GestureDetector(
onTap: widget.outsideDismiss ? _dismissDialog : null,
child: Material(
type: MaterialType.transparency,
child: new Center(
child: new SizedBox(
width: 120.0,
height: 120.0,
child: new Container(
decoration: ShapeDecoration(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(8.0),
),
),
),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new CircularProgressIndicator(),
new Padding(
padding: const EdgeInsets.only(
top: 20.0,
),
child: new Text(
widget.loadingText,
style: new TextStyle(fontSize: 12.0),
),
),
],
),
),
),
),
),
);
}
}

Some files were not shown because too many files have changed in this diff Show More