mirror of
https://github.com/alibaba/flutter-go.git
synced 2025-05-22 15:26:30 +08:00
add update version
This commit is contained in:
@ -25,7 +25,7 @@ Language: [English](https://github.com/alibaba/flutter-go/blob/master/README-en.
|
||||
|
||||
android下载地址:
|
||||
|
||||
<img src="https://img.alicdn.com/tfs/TB1jGgfQ7voK1RjSZFNXXcxMVXa-438-426.png" width="200px">
|
||||
<img src="https://img.alicdn.com/tfs/TB1ylxGTMHqK1RjSZFgXXa7JXXa-436-432.png" width="200px">
|
||||
|
||||
iphone下载地址:
|
||||
暂无
|
||||
|
17
android/.project
Normal file
17
android/.project
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>android</name>
|
||||
<comment>Project android created by Buildship.</comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
2
android/.settings/org.eclipse.buildship.core.prefs
Normal file
2
android/.settings/org.eclipse.buildship.core.prefs
Normal file
@ -0,0 +1,2 @@
|
||||
connection.project.dir=
|
||||
eclipse.preferences.version=1
|
6
android/app/.classpath
Normal file
6
android/app/.classpath
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
|
||||
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
|
||||
<classpathentry kind="output" path="bin/default"/>
|
||||
</classpath>
|
23
android/app/.project
Normal file
23
android/app/.project
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>app</name>
|
||||
<comment>Project app created by Buildship.</comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
2
android/app/.settings/org.eclipse.buildship.core.prefs
Normal file
2
android/app/.settings/org.eclipse.buildship.core.prefs
Normal file
@ -0,0 +1,2 @@
|
||||
connection.project.dir=..
|
||||
eclipse.preferences.version=1
|
BIN
assets/app.db
BIN
assets/app.db
Binary file not shown.
BIN
assets/images/FlutterGo.png
Normal file
BIN
assets/images/FlutterGo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
@ -530,6 +530,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = Launch2;
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 4WLT68XRNA;
|
||||
@ -546,7 +547,7 @@
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.alibaba.fluttergo;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "FlutterGO-alibaba-develop";
|
||||
PROVISIONING_PROFILE_SPECIFIER = FlutterGO_alibaba_distribution_app_store;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
|
@ -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>
|
12
lib/api/api.dart
Normal file
12
lib/api/api.dart
Normal file
@ -0,0 +1,12 @@
|
||||
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 DO_LOGIN = BASE_URL+'doLogin';//登陆
|
||||
|
||||
static const String CHECK_LOGIN = BASE_URL+'checkLogin';//验证登陆
|
||||
|
||||
static const String LOGOUT = BASE_URL+'logout';//退出登陆
|
||||
|
||||
static const String VERSION = BASE_URL+'getAppVersion';//检查版本
|
||||
}
|
@ -101,7 +101,7 @@ class _WidgetDemoState extends State<WidgetDemo> {
|
||||
// 插入操作
|
||||
_collectionControl
|
||||
.insert(Collection(name: widget.title, router: _router))
|
||||
.then((result) {
|
||||
.then((result) {
|
||||
if (this.mounted) {
|
||||
setState(() {
|
||||
_hasCollected = true;
|
||||
|
@ -1,21 +1,27 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluro/fluro.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'routers/routers.dart';
|
||||
import 'routers/application.dart';
|
||||
|
||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||
import 'package:flutter_go/utils/provider.dart';
|
||||
import 'package:flutter_go/utils/shared_preferences.dart';
|
||||
import 'package:flutter_go/views/home.dart';
|
||||
import 'package:flutter_go/model/search_history.dart';
|
||||
import 'package:flutter_go/utils/analytics.dart' as Analytics;
|
||||
import 'package:flutter_go/views/login_page/login_page.dart';
|
||||
import 'package:flutter_go/utils/data_utils.dart';
|
||||
|
||||
//import 'views/welcome_page/index.dart';
|
||||
|
||||
const int ThemeColor = 0xFFC91B3A;
|
||||
SpUtil sp;
|
||||
var db;
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
class MyApp extends StatefulWidget {
|
||||
MyApp() {
|
||||
final router = new Router();
|
||||
|
||||
@ -24,21 +30,68 @@ class MyApp extends StatelessWidget {
|
||||
Application.router = router;
|
||||
}
|
||||
|
||||
showWelcomePage(context) {
|
||||
//网络请求查看版本
|
||||
@override
|
||||
_MyAppState createState() => _MyAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
bool _hasLogin = false;
|
||||
bool _isLoading = true;
|
||||
String localVersion;
|
||||
String currVersion;
|
||||
|
||||
@override
|
||||
Future initState() {
|
||||
super.initState();
|
||||
|
||||
final platform = Theme.of(context).platform;
|
||||
print("platform:${platform}");
|
||||
// 暂时关掉欢迎介绍
|
||||
return AppPage();
|
||||
// bool showWelcome = sp.getBool(SharedPreferencesKeys.showWelcome);
|
||||
// if (showWelcome == null || showWelcome == true) {
|
||||
// return WelcomePage();
|
||||
// } else {
|
||||
// return AppPage();
|
||||
// }
|
||||
DataUtils.checkVersion({'name': 'FlutterGo'}).then((bool) {
|
||||
if (bool) {
|
||||
_UpdateURL();
|
||||
}
|
||||
}).catchError((onError) {
|
||||
print('获取失败:$onError');
|
||||
});
|
||||
|
||||
DataUtils.checkLogin().then((hasLogin) {
|
||||
setState(() {
|
||||
_hasLogin = hasLogin;
|
||||
_isLoading = false;
|
||||
});
|
||||
}).catchError((onError) {
|
||||
setState(() {
|
||||
_hasLogin = true;
|
||||
_isLoading = false;
|
||||
});
|
||||
print('身份信息验证失败:$onError');
|
||||
});
|
||||
}
|
||||
|
||||
showWelcomePage() {
|
||||
if (_isLoading) {
|
||||
return Container(
|
||||
color: const Color(ThemeColor),
|
||||
child: Center(
|
||||
child: SpinKitPouringHourglass(color: Colors.white),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// 判断是否已经登录
|
||||
if (_hasLogin) {
|
||||
return AppPage();
|
||||
} else {
|
||||
return LoginPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_UpdateURL() async {
|
||||
const currUrl =
|
||||
'https://github.com/alibaba/flutter-go/raw/master/FlutterGo.apk';
|
||||
if (await canLaunch(currUrl)) {
|
||||
await launch(currUrl);
|
||||
} else {
|
||||
throw 'Could not launch $currUrl';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -58,9 +111,9 @@ class MyApp extends StatelessWidget {
|
||||
size: 35.0,
|
||||
),
|
||||
),
|
||||
home: new Scaffold(body: showWelcomePage(context)),
|
||||
//debug banner
|
||||
// debugShowCheckedModeBanner: false,
|
||||
home: new Scaffold(body: showWelcomePage()),
|
||||
//去掉debug logo
|
||||
debugShowCheckedModeBanner: false,
|
||||
onGenerateRoute: Application.router.generator,
|
||||
navigatorObservers: <NavigatorObserver>[Analytics.observer],
|
||||
);
|
||||
|
24
lib/model/user_info.dart
Normal file
24
lib/model/user_info.dart
Normal file
@ -0,0 +1,24 @@
|
||||
class UserInfo {
|
||||
String username;
|
||||
int id;
|
||||
String avatarPic;
|
||||
String themeColor;
|
||||
String urlName;
|
||||
|
||||
UserInfo({
|
||||
this.avatarPic,
|
||||
this.id,
|
||||
this.themeColor,
|
||||
this.urlName,
|
||||
this.username,
|
||||
});
|
||||
|
||||
factory UserInfo.fromJson(Map<String, dynamic> json) {
|
||||
return UserInfo(
|
||||
avatarPic: json['avatar_pic'],
|
||||
id: int.parse(json['id']),
|
||||
username: json['name'],
|
||||
themeColor: json['theme_color'],
|
||||
urlName: json['url_name']);
|
||||
}
|
||||
}
|
64
lib/model/user_info_cache.dart
Normal file
64
lib/model/user_info_cache.dart
Normal file
@ -0,0 +1,64 @@
|
||||
/// @Author: 一凨
|
||||
/// @Date: 2019-01-07 16:24:42
|
||||
/// @Last Modified by: 一凨
|
||||
/// @Last Modified time: 2019-01-08 17:37:42
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_go/utils/sql.dart';
|
||||
|
||||
abstract class UserInfoInterface {
|
||||
String get username;
|
||||
String get password;
|
||||
}
|
||||
|
||||
class UserInfo implements UserInfoInterface {
|
||||
String username;
|
||||
String password;
|
||||
|
||||
UserInfo({this.username, this.password});
|
||||
|
||||
factory UserInfo.fromJSON(Map json){
|
||||
return UserInfo(username: json['username'],password: json['password']);
|
||||
}
|
||||
|
||||
Object toMap() {
|
||||
return {'username': username, 'password': password};
|
||||
}
|
||||
}
|
||||
|
||||
class UserInfoControlModel {
|
||||
final String table = 'userInfo';
|
||||
Sql sql;
|
||||
|
||||
UserInfoControlModel() {
|
||||
sql = Sql.setTable(table);
|
||||
}
|
||||
|
||||
// 获取所有的收藏
|
||||
|
||||
// 插入新的缓存
|
||||
Future insert(UserInfo userInfo) {
|
||||
var result =
|
||||
sql.insert({'username': userInfo.username, 'password': userInfo.password});
|
||||
return result;
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
Future<List<UserInfo>> getAllInfo() async {
|
||||
List list = await sql.getByCondition();
|
||||
List<UserInfo> resultList = [];
|
||||
list.forEach((item){
|
||||
print(item);
|
||||
resultList.add(UserInfo.fromJSON(item));
|
||||
});
|
||||
return resultList;
|
||||
}
|
||||
|
||||
// 清空表中数据
|
||||
Future deleteAll() async{
|
||||
return await sql.deleteAll();
|
||||
}
|
||||
|
||||
|
||||
}
|
29
lib/model/version.dart
Normal file
29
lib/model/version.dart
Normal file
@ -0,0 +1,29 @@
|
||||
class Data {
|
||||
String version;
|
||||
String name;
|
||||
|
||||
Data.fromJson(Map<String, dynamic> json)
|
||||
: version = json['version'],
|
||||
name = json['name'];
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'name: $name ,version: $version';
|
||||
}
|
||||
}
|
||||
|
||||
class Version {
|
||||
Data data;
|
||||
int status;
|
||||
bool success;
|
||||
|
||||
Version.formJson(Map<String, dynamic> json)
|
||||
: status = json['status'],
|
||||
success = json['success'],
|
||||
data = Data.fromJson(json['data']);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'status: $status ,success: $success,date: ${data.toString()}';
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import '../widgets/404.dart';
|
||||
import 'package:flutter_go/components/full_screen_code_dialog.dart';
|
||||
import 'package:flutter_go/views/web_page/web_view_page.dart';
|
||||
import 'package:flutter_go/views/home.dart';
|
||||
import 'package:flutter_go/views/login_page/login_page.dart';
|
||||
|
||||
// app的首页
|
||||
var homeHandler = new Handler(
|
||||
@ -26,6 +27,10 @@ var widgetNotFoundHandler = new Handler(
|
||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||
return new WidgetNotFound();
|
||||
});
|
||||
var loginPageHandler = new Handler(
|
||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||
return LoginPage();
|
||||
});
|
||||
|
||||
var fullScreenCodeDialog = new Handler(
|
||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||
|
@ -12,6 +12,7 @@ class Routes {
|
||||
static String widgetDemo = '/widget-demo';
|
||||
static String codeView = '/code-view';
|
||||
static String webViewPage = '/web-view-page';
|
||||
static String loginPage = '/loginpage';
|
||||
|
||||
static void configureRoutes(Router router) {
|
||||
List widgetDemosList = new WidgetDemoList().getDemos();
|
||||
@ -22,6 +23,7 @@ class Routes {
|
||||
|
||||
router.define('/category/:type', handler: categoryHandler);
|
||||
router.define('/category/error/404', handler: widgetNotFoundHandler);
|
||||
router.define(loginPage, handler: loginPageHandler);
|
||||
router.define(codeView,handler:fullScreenCodeDialog);
|
||||
router.define(webViewPage,handler:webViewPageHand);
|
||||
widgetDemosList.forEach((demo) {
|
||||
|
55
lib/utils/data_utils.dart
Normal file
55
lib/utils/data_utils.dart
Normal file
@ -0,0 +1,55 @@
|
||||
import 'dart:async' show Future;
|
||||
|
||||
import 'package:flutter_go/model/version.dart';
|
||||
import 'package:package_info/package_info.dart';
|
||||
|
||||
import './net_utils.dart';
|
||||
import '../model/user_info.dart';
|
||||
import 'package:flutter_go/api/api.dart';
|
||||
|
||||
class DataUtils {
|
||||
// 登陆获取用户信息
|
||||
static Future<UserInfo> doLogin(Map<String, String> params) async {
|
||||
var response = await NetUtils.post(Api.DO_LOGIN, params);
|
||||
UserInfo userInfo = UserInfo.fromJson(response['data']);
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
// 验证登陆
|
||||
|
||||
static Future<bool> checkLogin() async {
|
||||
var response = await NetUtils.get(Api.CHECK_LOGIN);
|
||||
print('验证登陆:$response');
|
||||
return response['success'];
|
||||
}
|
||||
|
||||
// 退出登陆
|
||||
static Future<bool> logout() async {
|
||||
var response = await NetUtils.get(Api.LOGOUT);
|
||||
print('退出登陆 $response');
|
||||
return response['success'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {"status":200,"data":{"version":"0.0.2","name":"FlutterGo"},"success":true}
|
||||
*/
|
||||
// 检查版本
|
||||
static Future<bool> checkVersion(Map<String, String> params) async {
|
||||
var response = await NetUtils.get(Api.VERSION, params);
|
||||
Version version = Version.formJson(response);
|
||||
var currVersion = version.data.version;
|
||||
PackageInfo.fromPlatform().then((PackageInfo packageInfo) {
|
||||
var localVersion = packageInfo.version;
|
||||
//0:相同、1:大于、-1:小于
|
||||
//currVersion: 1.0.6 // localVersion:0.0.2 //packbuildNumber 1 true
|
||||
//currVersion: 1.0.6 // localVersion:2.0.2 //packbuildNumber -1 false
|
||||
if (currVersion.compareTo(localVersion) == 1) {
|
||||
print('currVersion: true');
|
||||
return true;
|
||||
} else {
|
||||
print('currVersion: flase');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,19 +1,45 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'dart:io';
|
||||
import 'package:cookie_jar/cookie_jar.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
Map<String,dynamic> optHeader = {
|
||||
'accept-language':'zh-cn',
|
||||
'content-type':'application/json'
|
||||
};
|
||||
|
||||
var dio = new Dio();
|
||||
var dio = new Dio(BaseOptions(connectTimeout: 30000,headers: optHeader));
|
||||
|
||||
class NetUtils {
|
||||
|
||||
static Future get(String url,{Map<String,dynamic> params}) async{
|
||||
var response = await dio.get(url, data: params);
|
||||
return response.data;
|
||||
|
||||
static Future get(String url, [Map<String, dynamic> params]) async {
|
||||
var response;
|
||||
|
||||
// 设置代理 便于本地 charles 抓包
|
||||
// (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
|
||||
// (HttpClient client) {
|
||||
// client.findProxy = (uri) {
|
||||
// return "PROXY 30.10.26.193:8888";
|
||||
// };
|
||||
// };
|
||||
|
||||
Directory documentsDir = await getApplicationDocumentsDirectory();
|
||||
String documentsPath = documentsDir.path;
|
||||
var dir = new Directory("$documentsPath/cookies");
|
||||
await dir.create();
|
||||
// print('documentPath:${dir.path}');
|
||||
dio.interceptors.add(CookieManager(PersistCookieJar(dir: dir.path)));
|
||||
if (params != null) {
|
||||
response = await dio.get(url, queryParameters: params);
|
||||
} else {
|
||||
response = await dio.get(url);
|
||||
}
|
||||
return response.data;
|
||||
}
|
||||
|
||||
static Future post(String url,Map<String,dynamic> params) async{
|
||||
static Future post(String url, Map<String, dynamic> params) async {
|
||||
var response = await dio.post(url, data: params);
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'dart:async';
|
||||
|
||||
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
|
||||
@ -31,6 +31,10 @@ class Sql extends BaseModel {
|
||||
return await this.db.delete(tableName,where:'$key = ?',whereArgs:[value]);
|
||||
}
|
||||
|
||||
Future<int> deleteAll() async{
|
||||
return await this.db.delete(tableName);
|
||||
}
|
||||
|
||||
Future<List> getByCondition({Map<dynamic, dynamic> conditions}) async {
|
||||
if (conditions == null || conditions.isEmpty) {
|
||||
return this.get();
|
||||
|
@ -57,7 +57,7 @@ class FirstPageState extends State<FirstPage> with AutomaticKeepAliveClientMixin
|
||||
var pageTotal = 0;
|
||||
|
||||
try{
|
||||
var response = await NetUtils.get(juejin_flutter, params: _param);
|
||||
var response = await NetUtils.get(juejin_flutter, _param);
|
||||
responseList = response['d']['entrylist'];
|
||||
pageTotal = response['d']['total'];
|
||||
if (!(pageTotal is int) || pageTotal <= 0) {
|
||||
|
@ -57,7 +57,7 @@ class SubPageState extends State<SubPage> with AutomaticKeepAliveClientMixin{
|
||||
var pageTotal = 0;
|
||||
|
||||
try{
|
||||
var response = await NetUtils.get(juejin_flutter, params: _param);
|
||||
var response = await NetUtils.get(juejin_flutter, _param);
|
||||
responseList = response['d']['entrylist'];
|
||||
pageTotal = response['d']['total'];
|
||||
if (!(pageTotal is int) || pageTotal <= 0) {
|
||||
|
@ -10,7 +10,6 @@ import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_go/utils/shared_preferences.dart';
|
||||
import 'package:flutter_go/views/first_page/first_page.dart';
|
||||
import 'package:flutter_go/views/first_page/main_page.dart';
|
||||
import 'package:flutter_go/views/update_test.dart';
|
||||
import 'package:flutter_go/views/widget_page/widget_page.dart';
|
||||
import 'package:flutter_go/views/welcome_page/fourth_page.dart';
|
||||
import 'package:flutter_go/views/collection_page/collection_page.dart';
|
||||
@ -47,7 +46,6 @@ class _MyHomePageState extends State<AppPage>
|
||||
{'text': 'WIDGET', 'icon': Icon(Icons.extension)},
|
||||
{'text': '组件收藏', 'icon': Icon(Icons.favorite)},
|
||||
{'text': '关于手册', 'icon': Icon(Icons.import_contacts)},
|
||||
{'text': '点击更新', 'icon': Icon(Icons.update)}
|
||||
];
|
||||
|
||||
List<BottomNavigationBarItem> myTabs = [];
|
||||
@ -65,15 +63,11 @@ class _MyHomePageState extends State<AppPage>
|
||||
));
|
||||
}
|
||||
list
|
||||
|
||||
// ..add(FirstPage())
|
||||
..add(MainPage())
|
||||
..add(WidgetPage(Provider.db))
|
||||
..add(CollectionPage())
|
||||
..add(FourthPage())
|
||||
..add(UpdatePage(
|
||||
|
||||
));
|
||||
..add(FourthPage());
|
||||
}
|
||||
|
||||
@override
|
||||
|
295
lib/views/login_page/login_page.dart
Normal file
295
lib/views/login_page/login_page.dart
Normal file
@ -0,0 +1,295 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||
import 'package:flutter_go/utils/data_utils.dart';
|
||||
import 'package:flutter_go/views/home.dart';
|
||||
|
||||
import 'package:flutter_go/model/user_info_cache.dart';
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
@override
|
||||
_LoginPageState createState() => _LoginPageState();
|
||||
}
|
||||
|
||||
class _LoginPageState extends State<LoginPage> {
|
||||
// 利用FocusNode和_focusScopeNode来控制焦点 可以通过FocusNode.of(context)来获取widget树中默认的_focusScopeNode
|
||||
FocusNode _emailFocusNode = new FocusNode();
|
||||
FocusNode _passwordFocusNode = new FocusNode();
|
||||
FocusScopeNode _focusScopeNode = new FocusScopeNode();
|
||||
UserInfoControlModel _userInfoControlModel = new UserInfoControlModel();
|
||||
|
||||
GlobalKey<FormState> _signInFormKey = new GlobalKey();
|
||||
TextEditingController _userNameEditingController =
|
||||
new TextEditingController();
|
||||
TextEditingController _passwordEditingController =
|
||||
new TextEditingController();
|
||||
|
||||
bool isShowPassWord = false;
|
||||
String username = '';
|
||||
String password = '';
|
||||
bool isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
try {
|
||||
_userInfoControlModel.getAllInfo().then((list) {
|
||||
if (list.length > 0) {
|
||||
UserInfo _userInfo = list[0];
|
||||
print('获取的数据:${_userInfo.username} ${_userInfo.password}');
|
||||
setState(() {
|
||||
_userNameEditingController.text = _userInfo.username;
|
||||
_passwordEditingController.text = _userInfo.password;
|
||||
username = _userInfo.username;
|
||||
password = _userInfo.password;
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
print('读取用户本地存储的用户信息出错 $err');
|
||||
}
|
||||
}
|
||||
|
||||
// 创建登录界面的TextForm
|
||||
Widget buildSignInTextForm() {
|
||||
return new Container(
|
||||
decoration: new BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
),
|
||||
width: MediaQuery.of(context).size.width * 0.8,
|
||||
height: 190,
|
||||
// * Flutter提供了一个Form widget,它可以对输入框进行分组,然后进行一些统一操作,如输入内容校验、输入框重置以及输入内容保存。
|
||||
child: new Form(
|
||||
key: _signInFormKey,
|
||||
child: new Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 25, right: 25, top: 20, bottom: 20),
|
||||
child: new TextFormField(
|
||||
controller: _userNameEditingController,
|
||||
//关联焦点
|
||||
focusNode: _emailFocusNode,
|
||||
onEditingComplete: () {
|
||||
if (_focusScopeNode == null) {
|
||||
_focusScopeNode = FocusScope.of(context);
|
||||
}
|
||||
_focusScopeNode.requestFocus(_passwordFocusNode);
|
||||
},
|
||||
|
||||
decoration: new InputDecoration(
|
||||
icon: new Icon(
|
||||
Icons.email,
|
||||
color: Colors.black,
|
||||
),
|
||||
hintText: "Github 登录名",
|
||||
border: InputBorder.none),
|
||||
style: new TextStyle(fontSize: 16, color: Colors.black),
|
||||
//验证
|
||||
validator: (value) {
|
||||
if (value.isEmpty) {
|
||||
return "登录名不可为空!";
|
||||
}
|
||||
},
|
||||
onSaved: (value) {
|
||||
setState(() {
|
||||
username = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
new Container(
|
||||
height: 1,
|
||||
width: MediaQuery.of(context).size.width * 0.75,
|
||||
color: Colors.grey[400],
|
||||
),
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 25, right: 25, top: 20),
|
||||
child: new TextFormField(
|
||||
controller: _passwordEditingController,
|
||||
focusNode: _passwordFocusNode,
|
||||
decoration: new InputDecoration(
|
||||
icon: new Icon(
|
||||
Icons.lock,
|
||||
color: Colors.black,
|
||||
),
|
||||
hintText: "Github 登录密码",
|
||||
border: InputBorder.none,
|
||||
suffixIcon: new IconButton(
|
||||
icon: new Icon(
|
||||
Icons.remove_red_eye,
|
||||
color: Colors.black,
|
||||
),
|
||||
onPressed: showPassWord,
|
||||
),
|
||||
),
|
||||
//输入密码,需要用*****显示
|
||||
obscureText: !isShowPassWord,
|
||||
style: new TextStyle(fontSize: 16, color: Colors.black),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "密码不可为空!";
|
||||
}
|
||||
},
|
||||
onSaved: (value) {
|
||||
setState(() {
|
||||
password = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
new Container(
|
||||
height: 1,
|
||||
width: MediaQuery.of(context).size.width * 0.75,
|
||||
color: Colors.grey[400],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildSignInButton() {
|
||||
return new GestureDetector(
|
||||
child: new Container(
|
||||
padding: EdgeInsets.only(left: 42, right: 42, top: 10, bottom: 10),
|
||||
decoration: new BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(5)),
|
||||
color: Theme.of(context).primaryColor),
|
||||
child: new Text(
|
||||
"LOGIN",
|
||||
style: new TextStyle(fontSize: 25, color: Colors.white),
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
// 利用key来获取widget的状态FormState,可以用过FormState对Form的子孙FromField进行统一的操作
|
||||
if (_signInFormKey.currentState.validate()) {
|
||||
// 如果输入都检验通过,则进行登录操作
|
||||
// Scaffold.of(context)
|
||||
// .showSnackBar(new SnackBar(content: new Text("执行登录操作")));
|
||||
//调用所有自孩子的save回调,保存表单内容
|
||||
doLogin();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// 登陆操作
|
||||
doLogin() {
|
||||
_signInFormKey.currentState.save();
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
DataUtils.doLogin({'username': username, 'password': password})
|
||||
.then((result) {
|
||||
print(result);
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
try {
|
||||
_userInfoControlModel.deleteAll().then((result) {
|
||||
// print('删除结果:$result');
|
||||
_userInfoControlModel
|
||||
.insert(UserInfo(password: password, username: username))
|
||||
.then((value) {
|
||||
// print('存储成功:$value');
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
new MaterialPageRoute(builder: (context) => AppPage()),
|
||||
(route) => route == null);
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
new MaterialPageRoute(builder: (context) => AppPage()),
|
||||
(route) => route == null);
|
||||
}
|
||||
}).catchError((onError) {
|
||||
print(onError);
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 点击控制密码是否显示
|
||||
void showPassWord() {
|
||||
setState(() {
|
||||
isShowPassWord = !isShowPassWord;
|
||||
});
|
||||
}
|
||||
|
||||
Widget buildLoading() {
|
||||
if (isLoading) {
|
||||
return Opacity(
|
||||
opacity: .5,
|
||||
child: Container(
|
||||
width: MediaQuery.of(context).size.width * 0.85,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
color: Colors.black,
|
||||
),
|
||||
child: SpinKitPouringHourglass(color: Colors.white),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Container();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
child: Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
color: Theme.of(context).primaryColor,
|
||||
child: Center(
|
||||
child: Container(
|
||||
width: MediaQuery.of(context).size.width * 0.85,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
color: Colors.white,
|
||||
image: DecorationImage(
|
||||
image: AssetImage(
|
||||
'assets/images/paimaiLogo.png',
|
||||
),
|
||||
fit: BoxFit.scaleDown,
|
||||
alignment: Alignment.bottomRight,
|
||||
),
|
||||
),
|
||||
child: Stack(
|
||||
children: <Widget>[
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
SizedBox(height: 35.0),
|
||||
Image.asset(
|
||||
'assets/images/FlutterGo.png',
|
||||
fit: BoxFit.contain,
|
||||
width: 100.0,
|
||||
height: 100.0,
|
||||
),
|
||||
buildSignInTextForm(),
|
||||
buildSignInButton(),
|
||||
SizedBox(height: 35.0),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
child: buildLoading(),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,154 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_downloader/flutter_downloader.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:open_file/open_file.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class UpdatePage extends StatefulWidget {
|
||||
@override
|
||||
_UpdatePageState createState() => _UpdatePageState();
|
||||
}
|
||||
|
||||
class _UpdatePageState extends State<UpdatePage> {
|
||||
static const currUrl =
|
||||
'https://github.com/alibaba/flutter-go/raw/master/FlutterGo.apk';
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
FlutterDownloader.registerCallback((id, status, progress) async {
|
||||
setState(() {
|
||||
_currProgress = progress;
|
||||
});
|
||||
print(
|
||||
"id:${id}===== status=======:${status}=====progress======:${progress}");
|
||||
// 当下载完成时,调用安装
|
||||
if (status == DownloadTaskStatus.complete) {
|
||||
OpenFile.open(_localPath);
|
||||
FlutterDownloader.open(taskId: id);
|
||||
}
|
||||
});
|
||||
_permissisonReady = false;
|
||||
_prepare();
|
||||
}
|
||||
|
||||
bool _isLoading;
|
||||
bool _permissisonReady;
|
||||
String _localPath;
|
||||
int _currProgress = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 20),
|
||||
width: double.infinity,
|
||||
height: 10.0,
|
||||
child: new LinearProgressIndicator(
|
||||
value: _currProgress / 100,
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Text("现在是1.0.0",
|
||||
textAlign: TextAlign.center, style: TextStyle(fontSize: 20)),
|
||||
),
|
||||
Center(
|
||||
child: FlatButton(
|
||||
onPressed: () {
|
||||
print("点击${_permissisonReady}");
|
||||
if (_permissisonReady) {
|
||||
_requestDownload();
|
||||
} else {
|
||||
_checkPermission().then((hasGranted) {
|
||||
setState(() {
|
||||
_permissisonReady = hasGranted;
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
"点击获取新版本",
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
color: Colors.red[800],
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: FlatButton(
|
||||
onPressed: () {
|
||||
print("local===: _UpdateURL");
|
||||
_UpdateURL();
|
||||
},
|
||||
child: Text(
|
||||
"更新版本",
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
color: Colors.red[800],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
_UpdateURL() async {
|
||||
if (await canLaunch(currUrl)) {
|
||||
await launch(currUrl);
|
||||
} else {
|
||||
throw 'Could not launch $currUrl';
|
||||
}
|
||||
}
|
||||
|
||||
Future<Null> _prepare() async {
|
||||
_permissisonReady = await _checkPermission();
|
||||
}
|
||||
|
||||
//检查权限
|
||||
Future<bool> _checkPermission() async {
|
||||
if (Theme.of(context).platform == TargetPlatform.android) {
|
||||
PermissionStatus permission = await PermissionHandler()
|
||||
.checkPermissionStatus(PermissionGroup.storage);
|
||||
if (permission != PermissionStatus.granted) {
|
||||
Map<PermissionGroup, PermissionStatus> permissions =
|
||||
await PermissionHandler()
|
||||
.requestPermissions([PermissionGroup.storage]);
|
||||
if (permissions[PermissionGroup.storage] == PermissionStatus.granted) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void _requestDownload() async {
|
||||
final path = await _apkLocalPath;
|
||||
final taskId = await FlutterDownloader.enqueue(
|
||||
url: currUrl,
|
||||
fileName: "new_FlutterGo.apk",
|
||||
savedDir: path,
|
||||
showNotification: true,
|
||||
// show download progress in status bar (for Android)
|
||||
openFileFromNotification:
|
||||
true, // click on notification to open downloaded file (for Android)
|
||||
);
|
||||
}
|
||||
|
||||
// 获取安装地址
|
||||
Future<String> get _apkLocalPath async {
|
||||
// final directory = widget.platform == TargetPlatform.android
|
||||
// ? await getExternalStorageDirectory()
|
||||
// : await getApplicationDocumentsDirectory();
|
||||
|
||||
final directory = await getExternalStorageDirectory();
|
||||
_localPath = directory.path.toString() + "/download";
|
||||
return _localPath;
|
||||
}
|
||||
}
|
24
pubspec.lock
24
pubspec.lock
@ -51,12 +51,12 @@ packages:
|
||||
source: hosted
|
||||
version: "1.14.11"
|
||||
cookie_jar:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cookie_jar
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.8"
|
||||
version: "1.0.0"
|
||||
csslib:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -77,7 +77,7 @@ packages:
|
||||
name: dio
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.17"
|
||||
version: "2.1.3"
|
||||
event_bus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -132,6 +132,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
flutter_spinkit:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_spinkit
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@ -143,7 +150,7 @@ packages:
|
||||
name: flutter_webview_plugin
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.4"
|
||||
version: "0.3.5"
|
||||
html:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -157,7 +164,7 @@ packages:
|
||||
name: image_picker
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.0+1"
|
||||
version: "0.6.0+3"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -200,6 +207,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1+2"
|
||||
package_info:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: package_info
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.0+3"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -7,7 +7,7 @@ description: flutter_go
|
||||
# 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
|
||||
version: 1.0.6
|
||||
|
||||
environment:
|
||||
sdk: ">=2.0.0-dev.68.0 <3.0.0"
|
||||
@ -27,8 +27,10 @@ dependencies:
|
||||
url_launcher: ^5.0.2
|
||||
# 本地存储、收藏功能
|
||||
shared_preferences: ^0.4.3
|
||||
dio: ^1.0.6
|
||||
flutter_spinkit: "^3.1.0"
|
||||
dio: ^2.0.15
|
||||
flutter_webview_plugin: ^0.3.4
|
||||
cookie_jar: ^1.0.0
|
||||
# 日期格式化
|
||||
intl: 0.15.7
|
||||
city_pickers: ^0.0.1
|
||||
@ -42,6 +44,7 @@ dependencies:
|
||||
path_provider: ^1.1.0
|
||||
permission_handler: ^3.0.0
|
||||
open_file: ^2.0.1+2
|
||||
package_info: ^0.4.0+3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Reference in New Issue
Block a user