Skip to content

Commit

Permalink
feat: 实现「更多」页面 UI
Browse files Browse the repository at this point in the history
  • Loading branch information
dingguo committed Feb 16, 2019
1 parent 6e8a791 commit 2a7138c
Show file tree
Hide file tree
Showing 31 changed files with 1,440 additions and 48 deletions.
2 changes: 0 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ android {
}

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.yongf.flutter.easydeveloper"
minSdkVersion 16
targetSdkVersion 27
Expand All @@ -48,7 +47,6 @@ android {

buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
Expand Down
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="easy_developer"
android:label="SwissKnife"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
Expand Down
Binary file added assets/fonts/IcoMoon.ttf
Binary file not shown.
Binary file added assets/images/mountains.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/white_snake_1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/white_snake_2.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/white_snake_3.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/white_snake_4.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/white_snake_5.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/white_snake_6.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/white_snake_7.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/white_snake_8.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/white_snake_9.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions lib/common/routes_name.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
class Routes {
/// 通用路由
static const String LOGIN_PAGE = '/wancaibao/login';
static const String SETTINGS_PAGE = '/wancaibao/settings';
static const String ABOUT_PAGE = '/wancaibao/about';
static const String FEEDBACK_PAGE = '/wancaibao/feedback';
static const String MORE_PAGE = '/wancaibao/more';
static const String PASSWORD_MANAGE_PAGE = '/wancaibao/password-manage';
static const String ACCOUNT_INFO_PAGE = '/wancaibao/account-info';

/// 公共路由
static const String GUIDE_PAGE = '/common/guide';

/// 玩 Android 路由
static const String WAN_ANDROID_MAIN_PAGE = '/wanandroid/main';
static const String WAN_ANDROID_HOME_PAGE = '/wanandroid/home';
static const String WAN_ANDROID_PROJECT_PAGE = '/wanandroid/project';
static const String WAN_ANDROID_WECHAT_PAGE = '/wanandroid/wechat';
static const String WAN_ANDROID_KNOWLEDGE_PAGE = '/wanandroid/knowledge';
static const String WAN_ANDROID_MINE_PAGE = '/wanandroid/mine';
static const String WAN_ANDROID_WEBVIEW_PAGE = '/wanandroid/h5';
static const String WAN_ANDROID_MESSAGE_CENTER_PAGE =
'/wanandroid/message-center';
static const String WAN_ANDROID_COLLECTIONS_PAGE = '/wanandroid/collections';
static const String WAN_ANDROID_READLIST_PAGE = '/wanandroid/readlist';
static const String WAN_ANDROID_TAG_MANAGER_PAGE = '/wanandroid/tag-manager';
static const String WAN_ANDROID_FEEDBACK_PAGE = '/wanandroid/feedback';
static const String WAN_ANDROID_SETTINGS_PAGE = '/wanandroid/settings';
static const String WAN_ANDROID_LOGIN_PAGE = '/wanandroid/universal-login';
static const String WAN_ANDROID_ABOUT_PAGE = '/wanandroid/about';
static const String WAN_ANDROID_USER_INFO_PAGE = '/wanandroid/user-info';
static const String WAN_ANDROID_DEBUG_PAGE = '/wanandroid/debug-page';
}
27 changes: 27 additions & 0 deletions lib/data/net/dio_factory.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'package:dio/dio.dart';

class DioFactory {
factory DioFactory() => _getInstance();
static DioFactory _instance;
static Dio _dio;

DioFactory._internal() {
_dio = Dio();
}

static DioFactory _getInstance() {
if (_instance == null) {
_instance = DioFactory._internal();
}
return _instance;
}

getDio() {
return _dio;
}
}

//测试是否是单例
void main() {
print(DioFactory().getDio() == DioFactory().getDio());
}
86 changes: 86 additions & 0 deletions lib/data/net/swissknife_api.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import 'dart:io';

import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:easy_developer/data/net/dio_factory.dart';
import 'package:easy_developer/data/net/url_host.dart';
import 'package:easy_developer/data/net/url_path.dart';
import 'package:easy_developer/manager/user_manager.dart';
import 'package:path_provider/path_provider.dart';

// TODO: 还没找到一个自认为完美的缓存解决方案?
class SwissKnifeApi {
factory SwissKnifeApi() => _getInstance();
static SwissKnifeApi _instance;

SwissKnifeApi._internal() {
/// TODO: setup the WanAndroidApi.
}

static SwissKnifeApi _getInstance() {
if (_instance == null) {
_instance = SwissKnifeApi._internal();
}
return _instance;
}

/// 登录接口
Future<Response> login(String username, String password) async {
FormData formData = new FormData.from({
"username": "$username",
"password": "$password",
});
Dio dio = await _getDio();
return dio.post(UrlHost.WANANDROID_BASE_URL + UrlPath.LOGIN,
data: formData);
}

/// 注册接口
Future<Response> register(String username, String password) async {
FormData formData = FormData.from({
"username": "$username",
"password": "$password",
"repassword": "$password",
});
Dio dio = await _getDio();
return dio.post(UrlHost.WANANDROID_BASE_URL + UrlPath.REGISTER,
data: formData);
}

Future<Response> createIssue(String title, String body) async {
String url = UrlHost.GITHUB_API + UrlPath.GITHUB_ISSUE;
Dio dio = await _getDio();
Map<String, String> headers = {
"Content-Type": "application/json",
"Authorization": "token a9fa7c0aba0db77a72c0c6f2be54f40296ca14af"
};
Map<String, String> jsonBody = {"title": title, "body": body};
return await dio.post(url,
data: jsonBody, options: Options(headers: headers));
}

Future<Dio> _getDio() async {
Dio dio = DioFactory().getDio();
// bool isProxy = await SpUtils.getBool('enableDioProxy') ?? false;
bool isProxy = false;
String proxy = '192.168.2.163:8888';
// String proxy = '172.18.107.196:8888';
dio.onHttpClientCreate = (client) {
client.badCertificateCallback =
(X509Certificate cert, String host, int port) {
return isProxy && Platform.isAndroid;
};
client.findProxy = (url) {
return isProxy ? 'PROXY $proxy' : 'DIRECT';
};
};
Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path + "/cookie";
dio.cookieJar = PersistCookieJar(tempPath);
return dio;
}

Options _getOptions() {
return Options(headers: UserManager().getHeader());
}
}
6 changes: 5 additions & 1 deletion lib/data/net/url_host.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
class UrlHost {
/// 玩 Android api base url
static const String WANANDROID_BASE_URL = "http://www.wanandroid.com";

}
/// Github API
static const String GITHUB_API = "https://api.github.com";
}
8 changes: 7 additions & 1 deletion lib/data/net/url_path.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
class UrlPath {
/// 登录/注册
static const String LOGIN = "/user/login"; // 登录
static const String REGISTER = "/user/register"; // 注册
static const String LOGOUT = "/user/logout/json"; // 退出登录

}
/// issue
static const String GITHUB_ISSUE = "/repos/wangyongf/WAF/issues";
}
3 changes: 2 additions & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ class MyApp extends StatelessWidget {
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Easy Developer'),
home: MyHomePage(title: 'Swiss Knife'),
debugShowCheckedModeBanner: false,
);
}
}
111 changes: 111 additions & 0 deletions lib/manager/user_manager.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import 'dart:async';

import 'package:dio/dio.dart';
import 'package:easy_developer/data/net/swissknife_api.dart';
import 'package:easy_developer/util/date_utils.dart';
import 'package:easy_developer/util/sp_utils.dart';

class UserManager {
String userName;
String password;
String cookie;
DateTime cookieExpiresTime;
Map<String, String> _headerMap;

static final UserManager _singleton = UserManager._internal();

factory UserManager() {
return _singleton;
}

UserManager._internal() {
SpUtils.getUserName((String username) {
this.userName = username;
});
SpUtils.getPassword((String password) {
this.password = password;
});
SpUtils.getCookie((String cookie) {
this.cookie = cookie;
});
SpUtils.getCookieExpires((String cookieExpires) {
this.cookieExpiresTime = DateTime.parse(cookieExpires);
});
}

/// TODO: 通过 Cookie 的有效性来验证是否登录?
bool isLogin() {
return null != userName &&
userName.length >= 6 &&
null != password &&
password.length >= 6;
}

void logout() {
SpUtils.putUserName(null);
SpUtils.putPassword(null);
SpUtils.putCookie("");
SpUtils.putCookieExpires("");
userName = null;
password = null;
_headerMap = null;
}

void refreshUserData({Function callback}) {
SpUtils.getPassword((pw) {
this.password = pw;
});
SpUtils.getUserName((str) {
this.userName = str;
if (null != callback) {
callback();
}
});
SpUtils.getCookie((str) {
this.cookie = str;
_headerMap = null;
});
SpUtils.getCookieExpires((str) {
if (null != str && str.length > 0) {
this.cookieExpiresTime = DateTime.parse(str);
//提前3天请求新的cookie
if (cookieExpiresTime.isAfter(DateUtils.getDaysAgo(3))) {
Timer(Duration(milliseconds: 100), () {
autoLogin();
});
}
}
});
}

void login({String username, String password, Function callback}) {
_saveUserInfo(SwissKnifeApi().login(username, password), username, password,
callback: callback);
}

void register({String username, String password, Function callback}) {
_saveUserInfo(
SwissKnifeApi().register(username, password), username, password,
callback: callback);
}

void _saveUserInfo(
Future<Response> responseF, String userName, String password,
{Function callback}) {
responseF.then((response) {});
}

void autoLogin() {
if (isLogin()) {
login();
}
}

Map<String, String> getHeader() {
if (null == _headerMap) {
_headerMap = Map();
}
_headerMap["Cookie"] = cookie;
return _headerMap;
}
}
Loading

0 comments on commit 2a7138c

Please sign in to comment.