diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 950dc44..565be38 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -45,8 +45,6 @@ 15BE2897D1518D9BDD5AF970 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; - 3DB87B9B20AEA710C58FBCC8 /* 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 = ""; }; - 6F6754CA16FD7E3C9E4FCEB3 /* 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 = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -60,7 +58,6 @@ 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; BEBBA521223FEA6600583D52 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; - C1D6F379F6B3C85C2CC34999 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; D7BE9010C4F7FF033BA299B7 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; FDCB5E5FC17434D1FF8247D2 /* 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 = ""; }; /* End PBXFileReference section */ @@ -192,6 +189,7 @@ 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; DevelopmentTeam = 5K9P57YFSL; + ProvisioningStyle = Automatic; }; }; }; @@ -200,6 +198,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, Base, ); @@ -281,15 +280,11 @@ buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); 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"; - outputFileListPaths = ( - ); outputPaths = ( "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FlutterDownloaderDatabase.bundle", ); @@ -404,6 +399,8 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 5K9P57YFSL; ENABLE_BITCODE = NO; @@ -417,8 +414,9 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.flutter.beer; + PRODUCT_BUNDLE_IDENTIFIER = com.flutterken.ui; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; VERSIONING_SYSTEM = "apple-generic"; }; name = Profile; @@ -530,6 +528,8 @@ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 5K9P57YFSL; ENABLE_BITCODE = NO; @@ -543,8 +543,9 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.flutter.beer; + PRODUCT_BUNDLE_IDENTIFIER = com.flutterken.ui; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -554,6 +555,8 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 5K9P57YFSL; ENABLE_BITCODE = NO; @@ -567,8 +570,9 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.flutter.beer; + PRODUCT_BUNDLE_IDENTIFIER = com.flutterken.ui; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; diff --git a/lib/components/widget_comp.dart b/lib/components/widget_comp.dart index 402f313..be5db94 100644 --- a/lib/components/widget_comp.dart +++ b/lib/components/widget_comp.dart @@ -50,7 +50,7 @@ class IndexState extends State { backgroundImage: NetworkImage( info.avatarUrl, ), - radius: 35, + radius: 30, ), title: Text( info.name, @@ -75,10 +75,10 @@ class IndexState extends State { this._bodyList.length = 0; String mdText = await this.getMdFile(widget.mdUrl); String nameKey = AuthorList.list[widget.title]; - if (nameKey != null) { + /*if (nameKey != null) { this._bodyList.add(authorTile(nameKey)); this._bodyList.add(Divider()); - } + }*/ print('文档完成长度:${mdText.length}'); if (mdText.length > 30) { this._bodyList.add(await markdown_comp.Index(mdText)); @@ -117,6 +117,29 @@ class IndexState extends State { ); } + showCode(context) async { + /*if (Store.value(context).isPro) { + // 线上文档 + FluroRouter.router.navigateTo( + context, + 'webview?title=${widget.title}&url=${Uri.encodeComponent(Store.value(context).env.githubAssetOrigin+widget.mdUrl)}' + ); + } else {*/ + // 加载本地 + String mdStr = await AssetUtils.readLocaleFile(widget.mdUrl); + Navigator.of(context).push( + MaterialPageRoute(builder: (BuildContext build) { + return Scaffold( + appBar: AppBar(title: Text(widget.title),), + body: ListView( + children: [markdown_comp.Index(mdStr)], + ), + ); + }) + ); + //} + } + Future getMdFile(url) async { // bool productionEnv = Store.value(context).isPro; bool productionEnv = false; @@ -129,6 +152,15 @@ class IndexState extends State { getActions(context) { return [ + /*IconButton( + color: Color(AppTheme.blackColor), + icon: Icon( + Icons.code + ), + onPressed: () async { + this.showCode(context); + }, + ), IconButton( color: Color(AppTheme.blackColor), icon: Icon( @@ -140,7 +172,7 @@ class IndexState extends State { '/webview?title=${widget.title}&url=${Uri.encodeComponent(widget.originCodeUrl)}', ); }, - ), + ),*/ IconButton( icon: Icon(Icons.share), color: Color(AppTheme.blackColor), diff --git a/lib/config/index.dart b/lib/config/index.dart index 08e9168..787f047 100644 --- a/lib/config/index.dart +++ b/lib/config/index.dart @@ -2,5 +2,6 @@ import 'development.dart' as Development; import 'production.dart' as Production; const bool isPro = false; +const String owner_repo = 'efoxTeam/flutter-ui'; Object env = isPro ? Production.Config() : Development.Config(); diff --git a/lib/config/theme.dart b/lib/config/theme.dart index 0582100..4d34214 100644 --- a/lib/config/theme.dart +++ b/lib/config/theme.dart @@ -15,7 +15,7 @@ class AppTheme { static int blackColor = 0xFF000000; static int lineColor = 0xFFEEEEEE; static getThemeData(String theme) { - //print('==================================getThemeData=$theme'); + print('==================================getThemeData=$theme'); mainColor = materialColor[theme]; ThemeData themData = ThemeData( textTheme: TextTheme( diff --git a/lib/controller/index.dart b/lib/controller/index.dart index 76921bd..6e4b37d 100644 --- a/lib/controller/index.dart +++ b/lib/controller/index.dart @@ -3,12 +3,17 @@ import 'package:efox_flutter/store/index.dart' import 'package:efox_flutter/utils/appVersion.dart' show AppVersion; -void initState() { +void initState() async { // 获取版本号 - Store.valueNotCtx().getAppVersion(); + Store.value().getAppVersion(); // 登录 - Store.valueNotCtx().getLocalUserInfo(); + /*Store.value().getLocalUserInfo().then((res) { + if (res) { + Store.value().getUserStar(); + } + });*/ + // Store.value().getFlutterUIStar(); Future.delayed(Duration(seconds: 3), () { - AppVersion().check(Store.widgetCtx); + AppVersion().check(Store.context); }); } diff --git a/lib/http/index.dart b/lib/http/index.dart index 6e0dbba..9ae1631 100644 --- a/lib/http/index.dart +++ b/lib/http/index.dart @@ -47,10 +47,12 @@ Dio getDio({options, loading}) { print("返回值 ${response.data}"); print('=========【请求成功】End============'); await AppLoading.afterResponse(response.request.uri, loading); - return response; + return response; }, onError: (DioError e) async { - await AppLoading.afterResponse(e.request.uri, loading); + print('e.request.uri=======================${e.request}'); + if (e.request != null && e.request.uri != null) + await AppLoading.afterResponse(e.request.uri, loading); dynamic msg = e.message; dynamic code = 0; // 错误码 dynamic status = e.type; // http请求状态 @@ -60,7 +62,7 @@ Dio getDio({options, loading}) { status = e.response.statusCode; } print('========【请求失败 Start】============='); - print("请求地址 ${e.request.uri}"); + print("请求地址 ${e.request}"); print("状态码 ${status}"); print("返回msg ${msg}"); print('=========【请求失败 End】============'); @@ -68,16 +70,20 @@ Dio getDio({options, loading}) { }, )); dio.interceptors.add(LogInterceptor(responseBody: false)); //开启请求日志 - + return dio; } Future get({url, data = const {}, options, loading}) async { - return getDio(options: options, loading: loading ?? Map()) - .get(url); + return getDio(options: options, loading: loading ?? Map()).get(url); } Future post({url, data = const {}, options, loading}) async { return getDio(options: options, loading: loading ?? Map()) .post(url, data: data); } + +Future put({url, data = const {}, options, loading}) async { + return getDio(options: options, loading: loading ?? Map()) + .put(url, data: data); +} diff --git a/lib/http/loading.dart b/lib/http/loading.dart index 55e8074..ecac0b3 100644 --- a/lib/http/loading.dart +++ b/lib/http/loading.dart @@ -16,7 +16,7 @@ void beforeRequest(uri, Map options) { void afterResponse(uri, Map options) { dict.remove(uri); if (dict.length == 0 && loading == true) { - Navigator.of(Store.widgetCtx, rootNavigator: true).pop('close dialog'); + Navigator.of(Store.context, rootNavigator: true).pop('close dialog'); loading = false; } } @@ -31,7 +31,7 @@ void showAppLoading(Map options) { 'text': options['text'] ?? 'loading...' }; showDialog( - context: Store.widgetCtx, + context: Store.context, builder: (context) { return LoadingDialog(text: options['text']); }, diff --git a/lib/main.dart b/lib/main.dart index 895c764..7286253 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,11 +3,13 @@ import 'package:flutter_localizations/flutter_localizations.dart'; //语言包 import 'package:efox_flutter/lang/index.dart' show AppLocalizationsDelegate, AppLocalizations; import 'package:efox_flutter/lang/config.dart' show ConfigLanguage; -import 'package:efox_flutter/store/index.dart' - show Store, ConfigModel; //引用Store 层 +import 'package:efox_flutter/store/index.dart'; //引用Store 层 import 'package:efox_flutter/router/index.dart' show FluroRouter; //路由 import 'package:efox_flutter/config/theme.dart' show AppTheme; //主题 import 'package:efox_flutter/utils/analytics.dart' as Analytics; //统计 +import 'package:oktoast/oktoast.dart' show OKToast; +import 'package:efox_flutter/page/home.dart' as HomePage; + // import './mock/index.dart' as TestCase; class MainApp extends StatefulWidget { MainApp() { @@ -18,6 +20,7 @@ class MainApp extends StatefulWidget { @override MainAppState createState() => MainAppState(); } + class MainAppState extends State { // 定义全局 语言代理 AppLocalizationsDelegate _delegate; @@ -26,19 +29,21 @@ class MainAppState extends State { //实例化多语言 super.initState(); _delegate = AppLocalizationsDelegate(); - Store.setStoreCtx(context); // 初始化数据层 + + Future.delayed(Duration.zero, () async { + Store.value().getTheme(); + }); } @override Widget build(BuildContext context) { - Store.value(context).getTheme(); - - return Store.connect( - builder: (context, child, model) { + Store.of(context); + return Consumer( + builder: (context, configModel, child) { return MaterialApp( localeResolutionCallback: (deviceLocale, supportedLocales) { print( - 'deviceLocale=$deviceLocale supportedLocales=$supportedLocales'); + 'deviceLocale=$deviceLocale supportedLocales=$supportedLocales context=$context'); Locale _locale = supportedLocales.contains(deviceLocale) ? deviceLocale : Locale('zh'); @@ -55,8 +60,9 @@ class MainAppState extends State { _delegate, ], supportedLocales: ConfigLanguage.supportedLocales, - theme: AppTheme.getThemeData(model.theme), + theme: AppTheme.getThemeData(configModel.theme), onGenerateRoute: FluroRouter.router.generator, + // home: HomePage.Index(), navigatorObservers: [Analytics.observer], ); }, @@ -64,4 +70,8 @@ class MainAppState extends State { } } -void main() => runApp(Store.init(child: MainApp())); +void main() => runApp( + Store.init( + child: MainApp(), + ), + ); diff --git a/lib/package/README.md b/lib/package/README.md new file mode 100644 index 0000000..21f6e02 --- /dev/null +++ b/lib/package/README.md @@ -0,0 +1,2 @@ +# Flutter Packages for FLUTTER UI APP +> packages 为纯flutter 组件,沉淀通用组件,通用方法,通用模块 \ No newline at end of file diff --git a/lib/package/router/router.dart b/lib/package/router/router.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/page/app_login/index.dart b/lib/page/app_login/index.dart index b6e58fb..1db5abf 100644 --- a/lib/page/app_login/index.dart +++ b/lib/page/app_login/index.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'dart:math' as math; import 'package:efox_flutter/lang/index.dart' show AppLocalizations; import 'package:efox_flutter/store/index.dart' show Store, UserModel; +import './text.dart' as Content; class Index extends StatefulWidget { Index({Key key}) : super(key: key); @@ -23,9 +24,87 @@ class _IndexState extends State { */ renderOverlay(String text) { _overlayEntry?.remove(); + Size _size = MediaQuery.of(context).size; _overlayState = Overlay.of(context); _overlayEntry = OverlayEntry(builder: (context) { - return Center(child: Text(text)); + return Scaffold( + backgroundColor: Colors.transparent, + body: GestureDetector( + child: Stack( + children: [ + Opacity( + opacity: 0.75, + child: Container( + decoration: BoxDecoration( + color: Colors.black, + ), + ), + ), + SizedBox.expand( + child: Center( + child: SizedBox( + height: _size.height / 1.3, + width: _size.width / 1.3, + child: Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: Colors.grey, + blurRadius: 2, + // offset: Offset(0, 1), + ), + ], + ), + child: Column( + children: [ + Text( + "说明", + style: TextStyle( + color: Colors.black, + fontSize: 22, + ), + ), + SizedBox( + height: 10, + ), + Expanded( + child: SingleChildScrollView( + child: Text( + text, + textAlign: TextAlign.left, + style: TextStyle( + color: Colors.black, + fontSize: 16, + ), + ), + ), + ), + FlatButton( + textColor: Theme.of(context).primaryColor, + onPressed: () { + beforeDispose(); + }, + child: Padding( + padding: EdgeInsets.all(10), + child: Text("确定"), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + onTap: () { + beforeDispose(); + }, + ), + ); }); _overlayState.insert(_overlayEntry); } @@ -66,133 +145,135 @@ class _IndexState extends State { @override Widget build(BuildContext ctx) { - return WillPopScope( - child: Scaffold( - appBar: AppBar( - centerTitle: true, - title: Text( - AppLocalizations.$t('common.login'), - textAlign: TextAlign.center, - ), - automaticallyImplyLeading: false, + // return WillPopScope( + // child: , + // onWillPop: () { + // beforeDispose(); + // }, + // ); + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + AppLocalizations.$t('common.login'), + textAlign: TextAlign.center, ), - body: Builder(builder: (BuildContext context) { - return SingleChildScrollView( - child: Padding( - padding: EdgeInsets.symmetric(vertical: 50, horizontal: 24), - child: Form( - key: _formKey, - autovalidate: true, - child: Column( - children: [ - renderGithubImage(), - TextFormField( - controller: nameCtl, - autofocus: true, - decoration: InputDecoration( - labelText: AppLocalizations.$t('login.account'), - hintText: AppLocalizations.$t('login.account_tips'), - icon: Icon(Icons.person), - ), - validator: (v) { - return v.trim().length > 0 - ? null - : AppLocalizations.$t('login.account_error_tips'); - }, - ), - TextFormField( - controller: pwdCtl, - decoration: InputDecoration( - labelText: AppLocalizations.$t('login.password'), - hintText: AppLocalizations.$t('login.password_tips'), - icon: Icon(Icons.lock), - ), - obscureText: true, - validator: (v) { - return v.trim().length > 0 - ? null - : AppLocalizations.$t('login.password_error_tips'); - }, - ), - Padding( - padding: EdgeInsets.only(top: 50), - child: Row( - children: [ - Expanded( - child: RaisedButton( - padding: EdgeInsets.all(15), - color: Theme.of(context).primaryColor, - textColor: Theme.of(context) - .primaryTextTheme - .title - .color, - child: Text( - AppLocalizations.$t('common.login'), - ), - onPressed: () async { - if ((_formKey.currentState as FormState) - .validate()) { - await Store.value(context) - .loginController(context, { - 'name': nameCtl.text.trim(), - 'pwd': pwdCtl.text.trim() - }); - } - }, - ), - ) - ], - ), + // automaticallyImplyLeading: false, + ), + body: Builder(builder: (BuildContext context) { + return SingleChildScrollView( + child: Padding( + padding: EdgeInsets.symmetric(vertical: 50, horizontal: 24), + child: Form( + key: _formKey, + autovalidate: true, + child: Column( + children: [ + renderGithubImage(), + TextFormField( + controller: nameCtl, + autofocus: false, + decoration: InputDecoration( + labelText: AppLocalizations.$t('login.account'), + hintText: AppLocalizations.$t('login.account_tips'), + icon: Icon(Icons.person), ), - SizedBox( - height: 10, + validator: (v) { + return v.trim().length > 0 + ? null + : AppLocalizations.$t('login.account_error_tips'); + }, + ), + TextFormField( + controller: pwdCtl, + decoration: InputDecoration( + labelText: AppLocalizations.$t('login.password'), + hintText: AppLocalizations.$t('login.password_tips'), + icon: Icon(Icons.lock), ), - Row( - mainAxisAlignment: MainAxisAlignment.center, + obscureText: true, + validator: (v) { + return v.trim().length > 0 + ? null + : AppLocalizations.$t('login.password_error_tips'); + }, + ), + Padding( + padding: EdgeInsets.only(top: 50), + child: Row( children: [ - GestureDetector( - child: Text( - 'Github账户登录说明', - style: TextStyle( - decoration: TextDecoration.underline, - textBaseline: TextBaseline.ideographic, - decorationColor: Color(0xff000000), + Expanded( + child: RaisedButton( + padding: EdgeInsets.all(15), + color: Theme.of(context).primaryColor, + textColor: + Theme.of(context).primaryTextTheme.title.color, + child: Text( + AppLocalizations.$t('common.login'), ), + onPressed: () async { + if ((_formKey.currentState as FormState) + .validate()) { + await Store.value(context) + .loginController(context, { + 'name': nameCtl.text.trim(), + 'pwd': pwdCtl.text.trim() + }); + await Store.value(context) + .getUserStar(); + } + }, + ), + ) + ], + ), + ), + SizedBox( + height: 10, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Text( + 'Github账户登录说明', + style: TextStyle( + decoration: TextDecoration.underline, + textBaseline: TextBaseline.ideographic, + decorationColor: Color(0xff000000), ), - onTap: () { - renderOverlay(" Text 1"); - }, - ), - SizedBox( - width: 10, ), - GestureDetector( - child: Text( - '软件许可及服务协议', - style: TextStyle( - decoration: TextDecoration.underline, - textBaseline: TextBaseline.ideographic, - decorationColor: const Color(0xff000000), - ), + onTap: () { + renderOverlay(Content.loginText); + }, + ), + SizedBox( + width: 10, + ), + GestureDetector( + child: Text( + '软件许可及服务协议', + style: TextStyle( + decoration: TextDecoration.underline, + textBaseline: TextBaseline.ideographic, + decorationColor: const Color(0xff000000), ), - onTap: () { - renderOverlay(" Text 2"); - }, ), - ], - ) - ], - ), + onTap: () { + renderOverlay(" Text 2"); + }, + ), + ], + ) + ], ), ), - ); - }), - ), - onWillPop: () { - beforeDispose(); - }, + ), + ); + }), ); } + beforeDispose() { if (_overlayEntry != null) { _overlayEntry.remove(); diff --git a/lib/page/app_login/text.dart b/lib/page/app_login/text.dart new file mode 100644 index 0000000..3ecb96a --- /dev/null +++ b/lib/page/app_login/text.dart @@ -0,0 +1 @@ +const loginText = 'a1sd56a1sd56as1d'; \ No newline at end of file diff --git a/lib/page/comment/details.dart b/lib/page/comment/details.dart new file mode 100644 index 0000000..30fb8fa --- /dev/null +++ b/lib/page/comment/details.dart @@ -0,0 +1,274 @@ +import 'package:flutter/material.dart'; +import 'package:efox_flutter/lang/index.dart' show AppLocalizations; +import 'package:efox_flutter/store/index.dart'; +import 'package:efox_flutter/store/objects/flutter_ui_issues.dart' show IssuesContent; +import 'package:efox_flutter/store/objects/issues_comment.dart' show IssuesDetails; +import 'package:efox_flutter/page/app_login/index.dart' as LoginIndex; + +class Index extends StatefulWidget { + final int indexes; + Index({ Key key, @required this.indexes }):super(key: key); + @override + _IndexState createState() => _IndexState(); +} + +class _IndexState extends State { + final TextEditingController _controller = TextEditingController(); + var _getComment; + bool isCanSend = false; + + @override + void initState() { + // TODO: implement initState + super.initState(); + _getComment = this._getIssueComment(context); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + elevation: 0, + centerTitle: true, + title: Text( + AppLocalizations.$t('title_comment_detials') + ), + ), + body: Stack( + children: [ + Container( + margin: EdgeInsets.only(bottom: 50), + child: _ContentList(context), + ), + _SendComment(context) + ], + ) + ); + } + + Widget _ContentList (BuildContext context) { + return ListView( + children: [ + _IssueContent(context), + _CommentContent(context) + ], + ); + } + + Widget _IssueContent (BuildContext context) { + return Consumer( + builder: (context, model,child) { + IssuesContent issuesContent = model.flutter_ui_issues.issuesContent[widget.indexes]; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ListTile( + leading: CircleAvatar( + backgroundImage: NetworkImage( + issuesContent.user.avatarUrl??'http://thumb10.jfcdns.com/2018-06/bce5b10ae530f530.png', + ), + ), + title: Text('${issuesContent.user.login}'), + subtitle: Text('更新时间:${issuesContent.updatedAt}'), + ), + Container( + padding: EdgeInsets.fromLTRB(20.0, 20, 20, 0), + child: Text( + '${issuesContent.title != '' ? issuesContent.title : '无标题'} #${issuesContent.number}', + style: Theme.of(context).textTheme.title, + ), + ), + Container( + padding: EdgeInsets.fromLTRB(20.0, 10, 20, 20.0), + child: Text( + issuesContent.body, + // != '' ?issuesContent.body:'无主体内容' + style: Theme.of(context).textTheme.subhead + ), + ), + Divider( + height: 1, + ) + ], + ); + } + ); + } + + Widget _CommentContent (BuildContext context) { + return FutureBuilder( + future: _getComment, + // ignore: missing_return + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Container( + padding: EdgeInsets.all(20), + child: Center( + child: Text('loading....'), + ), + ); + } else if(snapshot.connectionState == ConnectionState.done) { + if (snapshot.hasData) { + return Consumer( + builder: (context, model,child) { + List items = []; + for(var issuesDetails in model.issues_comment.issuesDetails) { + items.add(_CommentContentItem(context, issuesDetails)); + } + return Column( + children: items, + ); + } + ); + } else { + return Center( + child: Text('暂无数据'), + ); + } + } + }, + ); + } + + Future _getIssueComment(BuildContext context) async { + IssuesContent issuesContent = Store.value(context).flutter_ui_issues.issuesContent[widget.indexes]; + await Store.value(context).getIssueComment(issuesContent.number); + return 'end'; + } + + Widget _CommentContentItem(BuildContext context, IssuesDetails issuesDetails) { + return Container( + padding: EdgeInsets.fromLTRB(10, 20, 10, 0), + child: Column( + children: [ + ListTile( + leading: CircleAvatar( + backgroundImage: NetworkImage( + issuesDetails.user.avatarUrl??'http://thumb10.jfcdns.com/2018-06/bce5b10ae530f530.png', + ), + ), + title: Text('${issuesDetails.user.login}'), + subtitle: Text('${issuesDetails.body}') + ), + Divider(height: 1,) + ], + ), + ); + } + + Widget _SendComment (BuildContext context) { + return Positioned( + bottom: 0, + left: 0, + child: Container( + width: MediaQuery.of(context).size.width, + height: 50, + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: BorderSide(width: 0.5, color: Color(int.parse('0xffe4e4e4'))) + ) + ), + child: Row( + children: [ + Expanded( + flex: 1, + child: _InputBox(), + ), + Consumer( + builder: (context, model,child) { + IssuesContent issuesContent = model.flutter_ui_issues.issuesContent[widget.indexes]; + return GestureDetector( + onTap: () async { + if (isCanSend) { + if (model.user.id != null) { + print('发布内容:${_controller.text}'); + bool isSendSuccess = await model.setIssueComment( + _controller.text, + issuesContent.number + ); + if (isSendSuccess) { + await this._getIssueComment(context); + _controller.text = ''; + } else { + print('网络错误'); + Scaffold.of(context).showSnackBar(SnackBar( + content: Text('网络出错,请稍后重试'), + )); + } + } else { + print('去往登陆'); + Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) { + return LoginIndex.Index(); + } + ) + ); + } + } + }, + child: Container( + padding: EdgeInsets.fromLTRB(0, 0, 10, 0), + child: Text( + '发布', + style: TextStyle( + color: isCanSend ? Theme.of(context).primaryColor : Colors.grey, + fontSize: 17 + ) + ), + ), + ); + } + ) + ], + ) + ), + ); + } + Widget _InputBox() { + return Container( + height: 30, + margin: EdgeInsets.fromLTRB(10, 10, 10, 10), + decoration: BoxDecoration( + color: Color(int.parse('0xffEDEDED')), + borderRadius: BorderRadius.circular(15) + ), + child: Row( + children: [ + Expanded( + flex: 1, + child: TextField( + controller: _controller, + autofocus: false, + onChanged: _onChanged, + style: TextStyle( + fontSize: 18.0, + color: Colors.black, + fontWeight: FontWeight.w300 + ), + decoration: InputDecoration( + contentPadding: EdgeInsets.fromLTRB(10, 0, 10, 0), + border: InputBorder.none, + hintText: '说点什么吧', + hintStyle: TextStyle(fontSize: 15) + ), + ), + ) + ], + ) + ); + } + + _onChanged(String text) { + if (text.length > 0) { + setState(() { + isCanSend = true; + }); + } else { + setState(() { + isCanSend = false; + }); + } + } +} \ No newline at end of file diff --git a/lib/page/comment/index.dart b/lib/page/comment/index.dart new file mode 100644 index 0000000..c6e70a4 --- /dev/null +++ b/lib/page/comment/index.dart @@ -0,0 +1,141 @@ +import 'package:flutter/material.dart'; +import 'package:efox_flutter/lang/index.dart' show AppLocalizations; +import 'package:efox_flutter/store/index.dart'; +import 'package:efox_flutter/store/objects/flutter_ui_issues.dart' + show IssuesContent; +import 'package:efox_flutter/router/index.dart' show FluroRouter; + +class Index extends StatefulWidget { + @override + _IndexState createState() => _IndexState(); +} + +class _IndexState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + elevation: 0, + centerTitle: true, + title: Text(AppLocalizations.$t('title_comment')), + ), + body: Container( + padding: EdgeInsets.fromLTRB(16.0, 0, 16.0, 0), + child: _CommentList(context), + )); + } + + Widget _CommentList(BuildContext context) { + return Consumer(builder: (context, model,child) { + if (model.flutter_ui_issues != null && + model.flutter_ui_issues.issuesContent != null && + model.flutter_ui_issues.issuesContent.length != 0) { + return ListView.builder( + itemCount: model.flutter_ui_issues.issuesContent.length, + itemBuilder: (context, index) { + return _CommentCard( + context, model.flutter_ui_issues.issuesContent[index], index); + }, + ); + } else { + return Center( + child: Text('loading....'), + ); + } + }); + } + + Widget _CommentCard( + BuildContext context, IssuesContent issuesContent, int index) { + return Padding( + child: GestureDetector( + onTap: () { + // Store.value(context).getIssueComment(issuesContent.number); + FluroRouter.router.navigateTo( + context, + '/commentdetails?indexes=${index}', + ); + }, + child: Card( + elevation: 4.0, + child: Stack( + alignment: Alignment.topCenter, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // AspectRatio( + // aspectRatio: 16/9, + // child: ClipRRect( + // borderRadius: BorderRadius.only( + // topLeft: Radius.circular(6.0), + // topRight: Radius.circular(6.0), + // bottomLeft: Radius.circular(6.0), + // bottomRight: Radius.circular(6.0) + // ), + // child: Image.network( + // issuesContent.user.avatarUrl??'http://thumb10.jfcdns.com/2018-06/bce5b10ae530f530.png', + // fit: BoxFit.cover, + // ), + // ), + // ), + ListTile( + leading: CircleAvatar( + backgroundImage: NetworkImage( + issuesContent.user.avatarUrl ?? + 'http://thumb10.jfcdns.com/2018-06/bce5b10ae530f530.png', + ), + ), + title: Text( + '${issuesContent.user.login}', + style: TextStyle(color: Theme.of(context).primaryColor), + ), + subtitle: Text('更新时间:${issuesContent.updatedAt}'), + trailing: Icon(Icons.keyboard_arrow_right), + ), + Container( + padding: EdgeInsets.fromLTRB(20.0, 20, 20, 0), + child: Text( + '${issuesContent.title != '' ? issuesContent.title : '无标题'} #${issuesContent.number}', + style: Theme.of(context).textTheme.title, + ), + ), + Container( + padding: EdgeInsets.fromLTRB(20.0, 10, 20, 0), + child: Column( + children: [ + Text('创建时间:${issuesContent.createdAt}', + style: TextStyle( + color: Colors.black54, fontSize: 12)), + Text('更新时间:${issuesContent.updatedAt}', + style: TextStyle( + color: Colors.black54, fontSize: 12)) + ], + )), + Container( + padding: EdgeInsets.fromLTRB(20.0, 10, 20, 20.0), + child: Text(issuesContent.body, + // != '' ?issuesContent.body:'无主体内容' + style: Theme.of(context).textTheme.subhead), + ) + ], + ), + // Positioned( + // top: 10, + // left: 10, + // child: Text( + // issuesContent.user.login, + // style: TextStyle( + // color: Theme.of(context).primaryColor, + // fontWeight: FontWeight.bold, + // fontSize: 20 + // ), + // ), + // ) + ], + )), + ), + padding: EdgeInsets.fromLTRB(0, 10, 0, 10), + ); + } +} diff --git a/lib/page/component/tabs.dart b/lib/page/component/tabs.dart index a64bf2e..84f9fbc 100644 --- a/lib/page/component/tabs.dart +++ b/lib/page/component/tabs.dart @@ -38,6 +38,7 @@ class _IndexState extends State final GlobalKey _scaffoldKey = new GlobalKey(); + // ignore: must_call_super Widget build(BuildContext context) { return Scaffold( key: _scaffoldKey, diff --git a/lib/page/home.dart b/lib/page/home.dart index d321a1c..53f7add 100644 --- a/lib/page/home.dart +++ b/lib/page/home.dart @@ -5,8 +5,10 @@ import 'package:efox_flutter/config/theme.dart' show AppTheme; import 'component/tabs.dart' as TabIndex; import 'mine/index.dart' as MyIndex; import 'app_login/index.dart' as LoginIndex; +import 'comment/index.dart' as CommentIndex; +import 'library/index.dart' as LibraryIndex; -import 'package:efox_flutter/store/index.dart' show Store, UserModel; +import 'package:efox_flutter/store/index.dart'; class Index extends StatefulWidget { @override @@ -30,20 +32,39 @@ class _IndexState extends State { } Widget _bottomNavigationBar() { - return BottomNavigationBar( - items: [ - BottomNavigationBarItem( - title: Text(AppLocalizations.$t('title_component')), - icon: Icon(Icons.dashboard)), - BottomNavigationBarItem( - title: Text(AppLocalizations.$t('title_my')), - icon: Icon(Icons.person_outline)), - ], - type: BottomNavigationBarType.fixed, - currentIndex: _currentIndex, - onTap: (int index) { - _pageController.jumpToPage(index); - }, + return BottomAppBar( + elevation: 0, + color: Color(0xFFf7f7f7), + shape: CircularNotchedRectangle(), + clipBehavior: Clip.antiAlias, + child: BottomNavigationBar( + //backgroundColor: Color(0xff000000), + elevation: 0, + backgroundColor: Color(0xFFf7f7f7), + type: BottomNavigationBarType.fixed, + items: [ + BottomNavigationBarItem( + title: Text(AppLocalizations.$t('title_component')), + icon: Icon(Icons.dashboard)), +/* BottomNavigationBarItem( + title: Text(AppLocalizations.$t('title_comment')), + icon: Icon(Icons.comment)), + BottomNavigationBarItem( + title: Text(AppLocalizations.$t('title_library')), + icon: Icon(Icons.library_add)),*/ + BottomNavigationBarItem( + title: Text(AppLocalizations.$t('title_my')), + icon: Icon(Icons.person_outline)), + ], + // type: BottomNavigationBarType.fixed, + currentIndex: _currentIndex, + onTap: (int index) { + /* if (index == 1 && _currentIndex != index) { + Store.value(context).getIssueFlutterUI(); + }*/ + _pageController.jumpToPage(index); + }, + ), ); } @@ -55,6 +76,7 @@ class _IndexState extends State { title: Text(AppLocalizations.$t('common.logout')), onTap: () { Store.value(context).clearUserInfo(); + Store.value(context).changeIsStar(false); }, ), ]; @@ -82,7 +104,8 @@ class _IndexState extends State { renderDrawer() { print('renderDrawer $context'); return Drawer( - child: Store.connect(builder: (context, child, model) { + child: Consumer(builder: (context, model,child) { + print('render model $model'); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -122,12 +145,52 @@ class _IndexState extends State { ); } + Widget _floatingActionButton(context) { + return Consumer(builder: (context, model,child) { + return FloatingActionButton( + backgroundColor: Theme.of(context).primaryColor, + onPressed: () { + if (!model.isStar && model.user.id != null) { + print('进行star'); + model.setStarFlutterUI(); + } else { + print('不满足进行star条件'); + if (model.user.id == null) { + Navigator.of(context) + .push(MaterialPageRoute(builder: (BuildContext context) { + return LoginIndex.Index(); + })); + } else { + Scaffold.of(context).showSnackBar(SnackBar( + content: Text('已star'), + )); + } + } + }, + child: Container( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + model.isStar + ? Icon(Icons.star, size: 20, color: Colors.white) + : Icon(Icons.star_border, size: 20, color: Colors.white), + Text('${model.flutter_ui_info.stargazersCount.toString()}', + style: TextStyle(color: Colors.white)) + ], + ), + ), + ); + }); + } + @override Widget build(BuildContext context) { - Store.setWidgetCtx(context); // 初始化scaffold的上下文作为全局上下文,提供弹窗等使用。 + // Store.setWidgetCtx(context); // 初始化scaffold的上下文作为全局上下文,提供弹窗等使用。 return Scaffold( drawer: renderDrawer(), bottomNavigationBar: _bottomNavigationBar(), + // floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, + // floatingActionButton: _floatingActionButton(context), body: PageView( controller: _pageController, physics: NeverScrollableScrollPhysics(), @@ -138,6 +201,8 @@ class _IndexState extends State { }, children: [ TabIndex.Index(), + // CommentIndex.Index(), + //LibraryIndex.Index(), MyIndex.Index(), ], ), diff --git a/lib/page/library/index.dart b/lib/page/library/index.dart new file mode 100644 index 0000000..2e710ea --- /dev/null +++ b/lib/page/library/index.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:efox_flutter/lang/index.dart' show AppLocalizations; + +class Index extends StatefulWidget { + @override + _IndexState createState() => _IndexState(); +} + +class _IndexState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + elevation: 0, + centerTitle: true, + title: Text( + AppLocalizations.$t('title_library') + ), + ), + body: Center( + child: Text('第三方库'), + ), + ); + } +} \ No newline at end of file diff --git a/lib/page/mine/index.dart b/lib/page/mine/index.dart index 4cadbd6..5f5a59e 100644 --- a/lib/page/mine/index.dart +++ b/lib/page/mine/index.dart @@ -108,6 +108,18 @@ class _IndexState extends State { ) ], ), + /* Divider( + color: Color(AppTheme.lineColor), + ), + ListTile( + onTap: () { + Store.value(context).setIsPro(); + }, + leading: Icon(Icons.verified_user), + title: Text(Store.value(context).isPro + ? AppLocalizations.$t('common_mine_1.doc_online') + : AppLocalizations.$t('common_mine_1.doc_offline')), + ),*/ Divider( color: Color(AppTheme.lineColor), ), diff --git a/lib/plugin/README.md b/lib/plugin/README.md new file mode 100644 index 0000000..88bf7f9 --- /dev/null +++ b/lib/plugin/README.md @@ -0,0 +1,2 @@ +# Flutter Plugin for FLUTTER UI APP +> plugin 为混编 flutter 组件,沉淀通用组件,通用方法,通用模块 \ No newline at end of file diff --git a/lib/router/index.dart b/lib/router/index.dart index 1841321..6ff106a 100644 --- a/lib/router/index.dart +++ b/lib/router/index.dart @@ -2,6 +2,8 @@ import 'package:flutter/widgets.dart'; import 'package:fluro/fluro.dart'; //首页 import 'package:efox_flutter/page/home.dart' as HomePage; +// 评论详细页面 +import 'package:efox_flutter/page/comment/details.dart' as CommentDetails; import 'package:efox_flutter/widget/index.dart' as WidgetConfig; import 'handles.dart'; //统计 @@ -24,6 +26,18 @@ class FluroRouter { }, ), ); + // 评论详情页面 + router.define( + '/commentdetails', + handler: Handler( + handlerFunc: (BuildContext context, Map params) { + String indexes = params["indexes"]?.first; + return CommentDetails.Index( + indexes: int.parse('${indexes}') + ); + } + ) + ); router.define('/webview', handler: webviewHandler); diff --git a/lib/store/index.dart b/lib/store/index.dart index 4872213..6f1130e 100644 --- a/lib/store/index.dart +++ b/lib/store/index.dart @@ -1,97 +1,38 @@ -import 'package:flutter/material.dart' show StreamBuilder; -import 'package:provide/provide.dart' - show - Provider, - Provide, - ProviderNode, - Providers, - ProvideMulti, - ProviderScope; -export 'package:provide/provide.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart' + show ChangeNotifierProvider, MultiProvider, Consumer, Provider; +export 'package:provider/provider.dart'; +// import './models/config_state_model.dart' show ConfigModel; import './models/user_model.dart' show UserModel; import './models/author_state_model.dart' show AuthorModel; export './models/config_state_model.dart' show ConfigModel; export './models/user_model.dart' show UserModel; export './models/author_state_model.dart' show AuthorModel; -import 'package:flutter/material.dart'; class Store { - static dynamic storeCtx = null; - static dynamic widgetCtx = null; - static init({model, child, dispose = true}) { - final providers = Providers() - ..provide(Provider.value(ConfigModel())) - ..provide(Provider.value(UserModel())) - ..provide(Provider.value(AuthorModel())); - - return ProviderNode( - child: child, - providers: providers, - dispose: dispose, - ); - } - /** - * 设置数据层上下文 - */ - static setStoreCtx(context) { - storeCtx = context; - } - - /** - * 设置Widget上下文 - */ - static setWidgetCtx(context) { - widgetCtx = context; + static BuildContext context; + static of(BuildContext context) { + Store.context ??= context; + return context; } - /** - * 获取 - */ - static T valueNotCtx() { - return Provide.value(storeCtx); - } - - /** - * 根据 Context 获取 - */ - static T value(context, {scope}) { - return Provide.value(context, scope: scope); - } - - /** - * 监听 - */ - static connect({builder, child, scope}) { - return Provide( - builder: builder, + static init({child}) { + return MultiProvider( child: child, - scope: scope, + providers: [ + ChangeNotifierProvider(builder: (_) => ConfigModel()), + ChangeNotifierProvider(builder: (_) => UserModel()), + ChangeNotifierProvider(builder: (_) => AuthorModel()), + ], ); } - /** - * 通过流的方式 监听 - */ - static stream({builder, model, context}) { - return StreamBuilder( - initialData: model, - stream: Provide.stream(context), - builder: builder); + static T value([BuildContext context]) { + context ??= Store.context; + return Provider.of(context); } - /** - * 链接多个类型 - */ - static multi( - {builder, - child, - List requestedValues, - Map> requestedScopedValues}) { - return ProvideMulti( - builder: builder, - child: child, - requestedValues: requestedValues, - requestedScopedValues: requestedScopedValues); - } + } + diff --git a/lib/store/index_for_provide.dart b/lib/store/index_for_provide.dart new file mode 100644 index 0000000..4872213 --- /dev/null +++ b/lib/store/index_for_provide.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart' show StreamBuilder; +import 'package:provide/provide.dart' + show + Provider, + Provide, + ProviderNode, + Providers, + ProvideMulti, + ProviderScope; +export 'package:provide/provide.dart'; +import './models/config_state_model.dart' show ConfigModel; +import './models/user_model.dart' show UserModel; +import './models/author_state_model.dart' show AuthorModel; +export './models/config_state_model.dart' show ConfigModel; +export './models/user_model.dart' show UserModel; +export './models/author_state_model.dart' show AuthorModel; +import 'package:flutter/material.dart'; + +class Store { + static dynamic storeCtx = null; + static dynamic widgetCtx = null; + static init({model, child, dispose = true}) { + final providers = Providers() + ..provide(Provider.value(ConfigModel())) + ..provide(Provider.value(UserModel())) + ..provide(Provider.value(AuthorModel())); + + return ProviderNode( + child: child, + providers: providers, + dispose: dispose, + ); + } + /** + * 设置数据层上下文 + */ + static setStoreCtx(context) { + storeCtx = context; + } + + /** + * 设置Widget上下文 + */ + static setWidgetCtx(context) { + widgetCtx = context; + } + + /** + * 获取 + */ + static T valueNotCtx() { + return Provide.value(storeCtx); + } + + /** + * 根据 Context 获取 + */ + static T value(context, {scope}) { + return Provide.value(context, scope: scope); + } + + /** + * 监听 + */ + static connect({builder, child, scope}) { + return Provide( + builder: builder, + child: child, + scope: scope, + ); + } + + /** + * 通过流的方式 监听 + */ + static stream({builder, model, context}) { + return StreamBuilder( + initialData: model, + stream: Provide.stream(context), + builder: builder); + } + + /** + * 链接多个类型 + */ + static multi( + {builder, + child, + List requestedValues, + Map> requestedScopedValues}) { + return ProvideMulti( + builder: builder, + child: child, + requestedValues: requestedValues, + requestedScopedValues: requestedScopedValues); + } +} diff --git a/lib/store/models/config_state_model.dart b/lib/store/models/config_state_model.dart index 633118f..20064b4 100644 --- a/lib/store/models/config_state_model.dart +++ b/lib/store/models/config_state_model.dart @@ -32,4 +32,9 @@ class ConfigModel extends ConfigInfo with ChangeNotifier { notifyListeners(); } + Future setIsPro() async { + isPro = !isPro; + notifyListeners(); + } + } diff --git a/lib/store/models/user_model.dart b/lib/store/models/user_model.dart index caf9102..74a02eb 100644 --- a/lib/store/models/user_model.dart +++ b/lib/store/models/user_model.dart @@ -6,8 +6,19 @@ import '../objects/user_info.dart' show UserInfo; import '../objects/github_resp_info.dart' show GitHubRespInfo; import 'package:efox_flutter/http/index.dart' as Http; import 'package:efox_flutter/utils/localStorage.dart' show LocalStorage; +import 'package:efox_flutter/config/index.dart' show owner_repo; +import '../objects/flutter_ui_info.dart' show FlutterUiInfo; +import '../objects/flutter_ui_issues.dart' show FlutterUiIssues; +import '../objects/issues_comment.dart' show IssuesComment; -class UserModel with ChangeNotifier { +class UserModelInfo { + bool isStar = false; // 用户是否star了flutter ui项目 + FlutterUiInfo flutter_ui_info = FlutterUiInfo(); // flutter ui项目信息 + FlutterUiIssues flutter_ui_issues = FlutterUiIssues(); // flutter ui的issues内容 + IssuesComment issues_comment = IssuesComment(); // issues comment内容 +} + +class UserModel extends UserModelInfo with ChangeNotifier { UserInfo user = UserInfo(); Future testLogin() async { return await Http.post(url: 'http://www.baidu.com').then((res) { @@ -91,12 +102,14 @@ class UserModel with ChangeNotifier { getLocalUserInfo() async { String data = await LocalStorage.get('githubUserInfo'); print("本地数据 $data"); + if (data != null) { + UserInfo user = UserInfo.fromJson(json.decode(data)); + setUserInfo(user); + return true; + } if (data == null) { - getUserInfo(); - return; + return await getUserInfo(); } - UserInfo user = UserInfo.fromJson(json.decode(data)); - setUserInfo(user); } /** @@ -120,4 +133,141 @@ class UserModel with ChangeNotifier { LocalStorage.remove('githubRespLoginToken'); notifyListeners(); } + + /** + * 修改star显示 + */ + changeIsStar(isShow){ + isStar = isShow; + notifyListeners(); + } + + /** + * 获取flutter ui star数量 + */ + getFlutterUIStar() { + var response = Http.get( + url: 'https://api.github.com/repos/$owner_repo' + ); + response.then((resp) { + print('获取flutter ui信息:$resp'); + flutter_ui_info= FlutterUiInfo.fromJson(resp.data); + notifyListeners(); + }).catchError((error) { + print('获取flutter ui信息出错:$error'); + }); + } + + /** + * 获取用户的star flutter ui信息 + */ + getUserStar() async { + var response = Http.get( + url: 'https://api.github.com/user/starred/$owner_repo' + ); + response.then((resp) { + print('用户的star信息状态码:${resp.statusCode}'); + if (resp.statusCode == 204) { + // TODO user have focused the repository + isStar = true; + notifyListeners(); + return ; + } + if (resp.statusCode == 404) { + // TODO user have not focused the repository + isStar = false; + notifyListeners(); + return; + } + }).catchError((error) { + print('获取用户star信息出错$error'); + if (error.statusCode == 404) { + // TODO user have not focused the repository + isStar = false; + notifyListeners(); + } + }); + } + + /** + * 用户star flutter ui项目 + */ + setStarFlutterUI() { + var response = Http.put( + url: 'https://api.github.com/user/starred/$owner_repo' + ); + response.then((resp) { + print('用户star flutter ui项目状态码: ${resp.statusCode}'); + if (resp.statusCode == 204) { + // star success + getFlutterUIStar(); + getUserStar(); + } + }).catchError((error) { + print('用户star flutter ui项目错误: $error'); + }); + } + + /** + * 获取flutter ui的issue内容 + */ + getIssueFlutterUI() { + var response = Http.get( + url: 'https://api.github.com/repos/$owner_repo/issues' + ); + response.then((resp) { + var data = { + "issues_content": resp.data + }; + print('获取flutter ui的issue内容:${data}'); + flutter_ui_issues = FlutterUiIssues.fromJson(data); + notifyListeners(); + return flutter_ui_issues; + }).catchError((error) { + print('获取flutter ui的issue内容出错:$error'); + }); + } + + /** + * 获取对应issue下的回复内容 + */ + getIssueComment(int number) async { + var response = await Http.get( + url: 'https://api.github.com/repos/$owner_repo/issues/$number/comments' + ); + try { + var data = { + "issues_details": response.data + }; + print('获取对应issue下的回复内容:${response.data}'); + issues_comment = IssuesComment.fromJson(data); + notifyListeners(); + } catch(error) { + print('获取对应issue下的回复内容出错:$error'); + } + } + + /** + * 回复issue评论 + */ + setIssueComment(String text, int number) async { + var data = { + "body": "$text" + }; + var response = await Http.post( + url: 'https://api.github.com/repos/$owner_repo/issues/$number/comments', + data: data + ); + try { + print('回复issue评论状态码:${response.statusCode}'); + if (response.statusCode == 201) { + return true; + } else { + return false; + } + } catch (error) { + print('回复issue评论出错:$error'); + return false; + } + } } diff --git a/lib/store/objects/flutter_ui_info.dart b/lib/store/objects/flutter_ui_info.dart new file mode 100644 index 0000000..af34786 --- /dev/null +++ b/lib/store/objects/flutter_ui_info.dart @@ -0,0 +1,492 @@ +class FlutterUiInfo { + int id; + String nodeId; + String name; + String fullName; + bool private; + Owner owner; + String htmlUrl; + String description; + bool fork; + String url; + String forksUrl; + String keysUrl; + String collaboratorsUrl; + String teamsUrl; + String hooksUrl; + String issueEventsUrl; + String eventsUrl; + String assigneesUrl; + String branchesUrl; + String tagsUrl; + String blobsUrl; + String gitTagsUrl; + String gitRefsUrl; + String treesUrl; + String statusesUrl; + String languagesUrl; + String stargazersUrl; + String contributorsUrl; + String subscribersUrl; + String subscriptionUrl; + String commitsUrl; + String gitCommitsUrl; + String commentsUrl; + String issueCommentUrl; + String contentsUrl; + String compareUrl; + String mergesUrl; + String archiveUrl; + String downloadsUrl; + String issuesUrl; + String pullsUrl; + String milestonesUrl; + String notificationsUrl; + String labelsUrl; + String releasesUrl; + String deploymentsUrl; + String createdAt; + String updatedAt; + String pushedAt; + String gitUrl; + String sshUrl; + String cloneUrl; + String svnUrl; + String homepage; + int size; + int stargazersCount; // star数量 + int watchersCount; + String language; + bool hasIssues; + bool hasProjects; + bool hasDownloads; + bool hasWiki; + bool hasPages; + int forksCount; // fork数量 + Null mirrorUrl; + bool archived; + bool disabled; + int openIssuesCount; + Null license; + int forks; + int openIssues; + int watchers; + String defaultBranch; + Organization organization; + int networkCount; + int subscribersCount; + + FlutterUiInfo( + {this.id, + this.nodeId, + this.name, + this.fullName, + this.private, + this.owner, + this.htmlUrl, + this.description, + this.fork, + this.url, + this.forksUrl, + this.keysUrl, + this.collaboratorsUrl, + this.teamsUrl, + this.hooksUrl, + this.issueEventsUrl, + this.eventsUrl, + this.assigneesUrl, + this.branchesUrl, + this.tagsUrl, + this.blobsUrl, + this.gitTagsUrl, + this.gitRefsUrl, + this.treesUrl, + this.statusesUrl, + this.languagesUrl, + this.stargazersUrl, + this.contributorsUrl, + this.subscribersUrl, + this.subscriptionUrl, + this.commitsUrl, + this.gitCommitsUrl, + this.commentsUrl, + this.issueCommentUrl, + this.contentsUrl, + this.compareUrl, + this.mergesUrl, + this.archiveUrl, + this.downloadsUrl, + this.issuesUrl, + this.pullsUrl, + this.milestonesUrl, + this.notificationsUrl, + this.labelsUrl, + this.releasesUrl, + this.deploymentsUrl, + this.createdAt, + this.updatedAt, + this.pushedAt, + this.gitUrl, + this.sshUrl, + this.cloneUrl, + this.svnUrl, + this.homepage, + this.size, + this.stargazersCount, + this.watchersCount, + this.language, + this.hasIssues, + this.hasProjects, + this.hasDownloads, + this.hasWiki, + this.hasPages, + this.forksCount, + this.mirrorUrl, + this.archived, + this.disabled, + this.openIssuesCount, + this.license, + this.forks, + this.openIssues, + this.watchers, + this.defaultBranch, + this.organization, + this.networkCount, + this.subscribersCount}); + + FlutterUiInfo.fromJson(Map json) { + id = json['id']; + nodeId = json['node_id']; + name = json['name']; + fullName = json['full_name']; + private = json['private']; + owner = json['owner'] != null ? new Owner.fromJson(json['owner']) : null; + htmlUrl = json['html_url']; + description = json['description']; + fork = json['fork']; + url = json['url']; + forksUrl = json['forks_url']; + keysUrl = json['keys_url']; + collaboratorsUrl = json['collaborators_url']; + teamsUrl = json['teams_url']; + hooksUrl = json['hooks_url']; + issueEventsUrl = json['issue_events_url']; + eventsUrl = json['events_url']; + assigneesUrl = json['assignees_url']; + branchesUrl = json['branches_url']; + tagsUrl = json['tags_url']; + blobsUrl = json['blobs_url']; + gitTagsUrl = json['git_tags_url']; + gitRefsUrl = json['git_refs_url']; + treesUrl = json['trees_url']; + statusesUrl = json['statuses_url']; + languagesUrl = json['languages_url']; + stargazersUrl = json['stargazers_url']; + contributorsUrl = json['contributors_url']; + subscribersUrl = json['subscribers_url']; + subscriptionUrl = json['subscription_url']; + commitsUrl = json['commits_url']; + gitCommitsUrl = json['git_commits_url']; + commentsUrl = json['comments_url']; + issueCommentUrl = json['issue_comment_url']; + contentsUrl = json['contents_url']; + compareUrl = json['compare_url']; + mergesUrl = json['merges_url']; + archiveUrl = json['archive_url']; + downloadsUrl = json['downloads_url']; + issuesUrl = json['issues_url']; + pullsUrl = json['pulls_url']; + milestonesUrl = json['milestones_url']; + notificationsUrl = json['notifications_url']; + labelsUrl = json['labels_url']; + releasesUrl = json['releases_url']; + deploymentsUrl = json['deployments_url']; + createdAt = json['created_at']; + updatedAt = json['updated_at']; + pushedAt = json['pushed_at']; + gitUrl = json['git_url']; + sshUrl = json['ssh_url']; + cloneUrl = json['clone_url']; + svnUrl = json['svn_url']; + homepage = json['homepage']; + size = json['size']; + stargazersCount = json['stargazers_count']; + watchersCount = json['watchers_count']; + language = json['language']; + hasIssues = json['has_issues']; + hasProjects = json['has_projects']; + hasDownloads = json['has_downloads']; + hasWiki = json['has_wiki']; + hasPages = json['has_pages']; + forksCount = json['forks_count']; + mirrorUrl = json['mirror_url']; + archived = json['archived']; + disabled = json['disabled']; + openIssuesCount = json['open_issues_count']; + license = json['license']; + forks = json['forks']; + openIssues = json['open_issues']; + watchers = json['watchers']; + defaultBranch = json['default_branch']; + organization = json['organization'] != null + ? new Organization.fromJson(json['organization']) + : null; + networkCount = json['network_count']; + subscribersCount = json['subscribers_count']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['node_id'] = this.nodeId; + data['name'] = this.name; + data['full_name'] = this.fullName; + data['private'] = this.private; + if (this.owner != null) { + data['owner'] = this.owner.toJson(); + } + data['html_url'] = this.htmlUrl; + data['description'] = this.description; + data['fork'] = this.fork; + data['url'] = this.url; + data['forks_url'] = this.forksUrl; + data['keys_url'] = this.keysUrl; + data['collaborators_url'] = this.collaboratorsUrl; + data['teams_url'] = this.teamsUrl; + data['hooks_url'] = this.hooksUrl; + data['issue_events_url'] = this.issueEventsUrl; + data['events_url'] = this.eventsUrl; + data['assignees_url'] = this.assigneesUrl; + data['branches_url'] = this.branchesUrl; + data['tags_url'] = this.tagsUrl; + data['blobs_url'] = this.blobsUrl; + data['git_tags_url'] = this.gitTagsUrl; + data['git_refs_url'] = this.gitRefsUrl; + data['trees_url'] = this.treesUrl; + data['statuses_url'] = this.statusesUrl; + data['languages_url'] = this.languagesUrl; + data['stargazers_url'] = this.stargazersUrl; + data['contributors_url'] = this.contributorsUrl; + data['subscribers_url'] = this.subscribersUrl; + data['subscription_url'] = this.subscriptionUrl; + data['commits_url'] = this.commitsUrl; + data['git_commits_url'] = this.gitCommitsUrl; + data['comments_url'] = this.commentsUrl; + data['issue_comment_url'] = this.issueCommentUrl; + data['contents_url'] = this.contentsUrl; + data['compare_url'] = this.compareUrl; + data['merges_url'] = this.mergesUrl; + data['archive_url'] = this.archiveUrl; + data['downloads_url'] = this.downloadsUrl; + data['issues_url'] = this.issuesUrl; + data['pulls_url'] = this.pullsUrl; + data['milestones_url'] = this.milestonesUrl; + data['notifications_url'] = this.notificationsUrl; + data['labels_url'] = this.labelsUrl; + data['releases_url'] = this.releasesUrl; + data['deployments_url'] = this.deploymentsUrl; + data['created_at'] = this.createdAt; + data['updated_at'] = this.updatedAt; + data['pushed_at'] = this.pushedAt; + data['git_url'] = this.gitUrl; + data['ssh_url'] = this.sshUrl; + data['clone_url'] = this.cloneUrl; + data['svn_url'] = this.svnUrl; + data['homepage'] = this.homepage; + data['size'] = this.size; + data['stargazers_count'] = this.stargazersCount; + data['watchers_count'] = this.watchersCount; + data['language'] = this.language; + data['has_issues'] = this.hasIssues; + data['has_projects'] = this.hasProjects; + data['has_downloads'] = this.hasDownloads; + data['has_wiki'] = this.hasWiki; + data['has_pages'] = this.hasPages; + data['forks_count'] = this.forksCount; + data['mirror_url'] = this.mirrorUrl; + data['archived'] = this.archived; + data['disabled'] = this.disabled; + data['open_issues_count'] = this.openIssuesCount; + data['license'] = this.license; + data['forks'] = this.forks; + data['open_issues'] = this.openIssues; + data['watchers'] = this.watchers; + data['default_branch'] = this.defaultBranch; + if (this.organization != null) { + data['organization'] = this.organization.toJson(); + } + data['network_count'] = this.networkCount; + data['subscribers_count'] = this.subscribersCount; + return data; + } +} + +class Owner { + String login; + int id; + String nodeId; + String avatarUrl; + String gravatarId; + String url; + String htmlUrl; + String followersUrl; + String followingUrl; + String gistsUrl; + String starredUrl; + String subscriptionsUrl; + String organizationsUrl; + String reposUrl; + String eventsUrl; + String receivedEventsUrl; + String type; + bool siteAdmin; + + Owner( + {this.login, + this.id, + this.nodeId, + this.avatarUrl, + this.gravatarId, + this.url, + this.htmlUrl, + this.followersUrl, + this.followingUrl, + this.gistsUrl, + this.starredUrl, + this.subscriptionsUrl, + this.organizationsUrl, + this.reposUrl, + this.eventsUrl, + this.receivedEventsUrl, + this.type, + this.siteAdmin}); + + Owner.fromJson(Map json) { + login = json['login']; + id = json['id']; + nodeId = json['node_id']; + avatarUrl = json['avatar_url']; + gravatarId = json['gravatar_id']; + url = json['url']; + htmlUrl = json['html_url']; + followersUrl = json['followers_url']; + followingUrl = json['following_url']; + gistsUrl = json['gists_url']; + starredUrl = json['starred_url']; + subscriptionsUrl = json['subscriptions_url']; + organizationsUrl = json['organizations_url']; + reposUrl = json['repos_url']; + eventsUrl = json['events_url']; + receivedEventsUrl = json['received_events_url']; + type = json['type']; + siteAdmin = json['site_admin']; + } + + Map toJson() { + final Map data = new Map(); + data['login'] = this.login; + data['id'] = this.id; + data['node_id'] = this.nodeId; + data['avatar_url'] = this.avatarUrl; + data['gravatar_id'] = this.gravatarId; + data['url'] = this.url; + data['html_url'] = this.htmlUrl; + data['followers_url'] = this.followersUrl; + data['following_url'] = this.followingUrl; + data['gists_url'] = this.gistsUrl; + data['starred_url'] = this.starredUrl; + data['subscriptions_url'] = this.subscriptionsUrl; + data['organizations_url'] = this.organizationsUrl; + data['repos_url'] = this.reposUrl; + data['events_url'] = this.eventsUrl; + data['received_events_url'] = this.receivedEventsUrl; + data['type'] = this.type; + data['site_admin'] = this.siteAdmin; + return data; + } +} + +class Organization { + String login; + int id; + String nodeId; + String avatarUrl; + String gravatarId; + String url; + String htmlUrl; + String followersUrl; + String followingUrl; + String gistsUrl; + String starredUrl; + String subscriptionsUrl; + String organizationsUrl; + String reposUrl; + String eventsUrl; + String receivedEventsUrl; + String type; + bool siteAdmin; + + Organization( + {this.login, + this.id, + this.nodeId, + this.avatarUrl, + this.gravatarId, + this.url, + this.htmlUrl, + this.followersUrl, + this.followingUrl, + this.gistsUrl, + this.starredUrl, + this.subscriptionsUrl, + this.organizationsUrl, + this.reposUrl, + this.eventsUrl, + this.receivedEventsUrl, + this.type, + this.siteAdmin}); + + Organization.fromJson(Map json) { + login = json['login']; + id = json['id']; + nodeId = json['node_id']; + avatarUrl = json['avatar_url']; + gravatarId = json['gravatar_id']; + url = json['url']; + htmlUrl = json['html_url']; + followersUrl = json['followers_url']; + followingUrl = json['following_url']; + gistsUrl = json['gists_url']; + starredUrl = json['starred_url']; + subscriptionsUrl = json['subscriptions_url']; + organizationsUrl = json['organizations_url']; + reposUrl = json['repos_url']; + eventsUrl = json['events_url']; + receivedEventsUrl = json['received_events_url']; + type = json['type']; + siteAdmin = json['site_admin']; + } + + Map toJson() { + final Map data = new Map(); + data['login'] = this.login; + data['id'] = this.id; + data['node_id'] = this.nodeId; + data['avatar_url'] = this.avatarUrl; + data['gravatar_id'] = this.gravatarId; + data['url'] = this.url; + data['html_url'] = this.htmlUrl; + data['followers_url'] = this.followersUrl; + data['following_url'] = this.followingUrl; + data['gists_url'] = this.gistsUrl; + data['starred_url'] = this.starredUrl; + data['subscriptions_url'] = this.subscriptionsUrl; + data['organizations_url'] = this.organizationsUrl; + data['repos_url'] = this.reposUrl; + data['events_url'] = this.eventsUrl; + data['received_events_url'] = this.receivedEventsUrl; + data['type'] = this.type; + data['site_admin'] = this.siteAdmin; + return data; + } +} \ No newline at end of file diff --git a/lib/store/objects/flutter_ui_issues.dart b/lib/store/objects/flutter_ui_issues.dart new file mode 100644 index 0000000..ddf1f82 --- /dev/null +++ b/lib/store/objects/flutter_ui_issues.dart @@ -0,0 +1,254 @@ +class FlutterUiIssues { + List issuesContent; + + FlutterUiIssues({this.issuesContent}); + + FlutterUiIssues.fromJson(Map json) { + if (json['issues_content'] != null) { + issuesContent = new List(); + json['issues_content'].forEach((v) { + issuesContent.add(new IssuesContent.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + if (this.issuesContent != null) { + data['issues_content'] = + this.issuesContent.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class IssuesContent { + String url; + String repositoryUrl; + String labelsUrl; + String commentsUrl; + String eventsUrl; + String htmlUrl; + int id; + String nodeId; + int number; + String title; + User user; + List labels; + String state; + bool locked; + List assignees; + int comments; + String createdAt; + String updatedAt; + String authorAssociation; + String body; + + IssuesContent( + {this.url, + this.repositoryUrl, + this.labelsUrl, + this.commentsUrl, + this.eventsUrl, + this.htmlUrl, + this.id, + this.nodeId, + this.number, + this.title, + this.user, + this.labels, + this.state, + this.locked, + this.assignees, + this.comments, + this.createdAt, + this.updatedAt, + this.authorAssociation, + this.body}); + + IssuesContent.fromJson(Map json) { + url = json['url']; + repositoryUrl = json['repository_url']; + labelsUrl = json['labels_url']; + commentsUrl = json['comments_url']; + eventsUrl = json['events_url']; + htmlUrl = json['html_url']; + id = json['id']; + nodeId = json['node_id']; + number = json['number']; + title = json['title']; + user = json['user'] != null ? new User.fromJson(json['user']) : null; + labels = json['labels'].cast(); + state = json['state']; + locked = json['locked']; + assignees = json['assignees'].cast(); + comments = json['comments']; + createdAt = json['created_at']; + updatedAt = json['updated_at']; + authorAssociation = json['author_association']; + body = json['body']; + } + + Map toJson() { + final Map data = new Map(); + data['url'] = this.url; + data['repository_url'] = this.repositoryUrl; + data['labels_url'] = this.labelsUrl; + data['comments_url'] = this.commentsUrl; + data['events_url'] = this.eventsUrl; + data['html_url'] = this.htmlUrl; + data['id'] = this.id; + data['node_id'] = this.nodeId; + data['number'] = this.number; + data['title'] = this.title; + if (this.user != null) { + data['user'] = this.user.toJson(); + } + data['labels'] = this.labels; + data['state'] = this.state; + data['locked'] = this.locked; + data['assignees'] = this.assignees; + data['comments'] = this.comments; + data['created_at'] = this.createdAt; + data['updated_at'] = this.updatedAt; + data['author_association'] = this.authorAssociation; + data['body'] = this.body; + return data; + } +} + +class User { + String login; + int id; + String nodeId; + String avatarUrl; + String gravatarId; + String url; + String htmlUrl; + String followersUrl; + String followingUrl; + String gistsUrl; + String starredUrl; + String subscriptionsUrl; + String organizationsUrl; + String reposUrl; + String eventsUrl; + String receivedEventsUrl; + String type; + bool siteAdmin; + + User( + {this.login, + this.id, + this.nodeId, + this.avatarUrl, + this.gravatarId, + this.url, + this.htmlUrl, + this.followersUrl, + this.followingUrl, + this.gistsUrl, + this.starredUrl, + this.subscriptionsUrl, + this.organizationsUrl, + this.reposUrl, + this.eventsUrl, + this.receivedEventsUrl, + this.type, + this.siteAdmin}); + + User.fromJson(Map json) { + login = json['login']; + id = json['id']; + nodeId = json['node_id']; + avatarUrl = json['avatar_url']; + gravatarId = json['gravatar_id']; + url = json['url']; + htmlUrl = json['html_url']; + followersUrl = json['followers_url']; + followingUrl = json['following_url']; + gistsUrl = json['gists_url']; + starredUrl = json['starred_url']; + subscriptionsUrl = json['subscriptions_url']; + organizationsUrl = json['organizations_url']; + reposUrl = json['repos_url']; + eventsUrl = json['events_url']; + receivedEventsUrl = json['received_events_url']; + type = json['type']; + siteAdmin = json['site_admin']; + } + + Map toJson() { + final Map data = new Map(); + data['login'] = this.login; + data['id'] = this.id; + data['node_id'] = this.nodeId; + data['avatar_url'] = this.avatarUrl; + data['gravatar_id'] = this.gravatarId; + data['url'] = this.url; + data['html_url'] = this.htmlUrl; + data['followers_url'] = this.followersUrl; + data['following_url'] = this.followingUrl; + data['gists_url'] = this.gistsUrl; + data['starred_url'] = this.starredUrl; + data['subscriptions_url'] = this.subscriptionsUrl; + data['organizations_url'] = this.organizationsUrl; + data['repos_url'] = this.reposUrl; + data['events_url'] = this.eventsUrl; + data['received_events_url'] = this.receivedEventsUrl; + data['type'] = this.type; + data['site_admin'] = this.siteAdmin; + return data; + } +} + + + + + +// [ +// { +// "url": "https://api.github.com/repos/efoxTeam/flutter-ui/issues/53", +// "repository_url": "https://api.github.com/repos/efoxTeam/flutter-ui", +// "labels_url": "https://api.github.com/repos/efoxTeam/flutter-ui/issues/53/labels{/name}", +// "comments_url": "https://api.github.com/repos/efoxTeam/flutter-ui/issues/53/comments", +// "events_url": "https://api.github.com/repos/efoxTeam/flutter-ui/issues/53/events", +// "html_url": "https://github.com/efoxTeam/flutter-ui/issues/53", +// "id": 454062553, +// "node_id": "MDU6SXNzdWU0NTQwNjI1NTM=", +// "number": 53, +// "title": "test issue", +// "user": { +// "login": "DIVINER-onlys", +// "id": 35843543, +// "node_id": "MDQ6VXNlcjM1ODQzNTQz", +// "avatar_url": "https://avatars0.githubusercontent.com/u/35843543?v=4", +// "gravatar_id": "", +// "url": "https://api.github.com/users/DIVINER-onlys", +// "html_url": "https://github.com/DIVINER-onlys", +// "followers_url": "https://api.github.com/users/DIVINER-onlys/followers", +// "following_url": "https://api.github.com/users/DIVINER-onlys/following{/other_user}", +// "gists_url": "https://api.github.com/users/DIVINER-onlys/gists{/gist_id}", +// "starred_url": "https://api.github.com/users/DIVINER-onlys/starred{/owner}{/repo}", +// "subscriptions_url": "https://api.github.com/users/DIVINER-onlys/subscriptions", +// "organizations_url": "https://api.github.com/users/DIVINER-onlys/orgs", +// "repos_url": "https://api.github.com/users/DIVINER-onlys/repos", +// "events_url": "https://api.github.com/users/DIVINER-onlys/events{/privacy}", +// "received_events_url": "https://api.github.com/users/DIVINER-onlys/received_events", +// "type": "User", +// "site_admin": false +// }, +// "labels": [""], +// "state": "open", +// "locked": false, +// "assignee": null, +// "assignees": [""], +// "milestone": null, +// "comments": 1, +// "created_at": "2019-06-10T08:47:37Z", +// "updated_at": "2019-06-10T08:51:54Z", +// "closed_at": null, +// "author_association": "NONE", +// "body": "api test" +// } +// ] \ No newline at end of file diff --git a/lib/store/objects/issues_comment.dart b/lib/store/objects/issues_comment.dart new file mode 100644 index 0000000..aefc74a --- /dev/null +++ b/lib/store/objects/issues_comment.dart @@ -0,0 +1,199 @@ +class IssuesComment { + List issuesDetails; + + IssuesComment({this.issuesDetails}); + + IssuesComment.fromJson(Map json) { + if (json['issues_details'] != null) { + issuesDetails = new List(); + json['issues_details'].forEach((v) { + issuesDetails.add(new IssuesDetails.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + if (this.issuesDetails != null) { + data['issues_details'] = + this.issuesDetails.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class IssuesDetails { + String url; + String htmlUrl; + String issueUrl; + int id; + String nodeId; + User user; + String createdAt; + String updatedAt; + String authorAssociation; + String body; + + IssuesDetails( + {this.url, + this.htmlUrl, + this.issueUrl, + this.id, + this.nodeId, + this.user, + this.createdAt, + this.updatedAt, + this.authorAssociation, + this.body}); + + IssuesDetails.fromJson(Map json) { + url = json['url']; + htmlUrl = json['html_url']; + issueUrl = json['issue_url']; + id = json['id']; + nodeId = json['node_id']; + user = json['user'] != null ? new User.fromJson(json['user']) : null; + createdAt = json['created_at']; + updatedAt = json['updated_at']; + authorAssociation = json['author_association']; + body = json['body']; + } + + Map toJson() { + final Map data = new Map(); + data['url'] = this.url; + data['html_url'] = this.htmlUrl; + data['issue_url'] = this.issueUrl; + data['id'] = this.id; + data['node_id'] = this.nodeId; + if (this.user != null) { + data['user'] = this.user.toJson(); + } + data['created_at'] = this.createdAt; + data['updated_at'] = this.updatedAt; + data['author_association'] = this.authorAssociation; + data['body'] = this.body; + return data; + } +} + +class User { + String login; + int id; + String nodeId; + String avatarUrl; + String gravatarId; + String url; + String htmlUrl; + String followersUrl; + String followingUrl; + String gistsUrl; + String starredUrl; + String subscriptionsUrl; + String organizationsUrl; + String reposUrl; + String eventsUrl; + String receivedEventsUrl; + String type; + bool siteAdmin; + + User( + {this.login, + this.id, + this.nodeId, + this.avatarUrl, + this.gravatarId, + this.url, + this.htmlUrl, + this.followersUrl, + this.followingUrl, + this.gistsUrl, + this.starredUrl, + this.subscriptionsUrl, + this.organizationsUrl, + this.reposUrl, + this.eventsUrl, + this.receivedEventsUrl, + this.type, + this.siteAdmin}); + + User.fromJson(Map json) { + login = json['login']; + id = json['id']; + nodeId = json['node_id']; + avatarUrl = json['avatar_url']; + gravatarId = json['gravatar_id']; + url = json['url']; + htmlUrl = json['html_url']; + followersUrl = json['followers_url']; + followingUrl = json['following_url']; + gistsUrl = json['gists_url']; + starredUrl = json['starred_url']; + subscriptionsUrl = json['subscriptions_url']; + organizationsUrl = json['organizations_url']; + reposUrl = json['repos_url']; + eventsUrl = json['events_url']; + receivedEventsUrl = json['received_events_url']; + type = json['type']; + siteAdmin = json['site_admin']; + } + + Map toJson() { + final Map data = new Map(); + data['login'] = this.login; + data['id'] = this.id; + data['node_id'] = this.nodeId; + data['avatar_url'] = this.avatarUrl; + data['gravatar_id'] = this.gravatarId; + data['url'] = this.url; + data['html_url'] = this.htmlUrl; + data['followers_url'] = this.followersUrl; + data['following_url'] = this.followingUrl; + data['gists_url'] = this.gistsUrl; + data['starred_url'] = this.starredUrl; + data['subscriptions_url'] = this.subscriptionsUrl; + data['organizations_url'] = this.organizationsUrl; + data['repos_url'] = this.reposUrl; + data['events_url'] = this.eventsUrl; + data['received_events_url'] = this.receivedEventsUrl; + data['type'] = this.type; + data['site_admin'] = this.siteAdmin; + return data; + } +} + +// { +// "issues_details": [ +// { +// "url": "https://api.github.com/repos/efoxTeam/flutter-ui/issues/comments/500342145", +// "html_url": "https://github.com/efoxTeam/flutter-ui/issues/53#issuecomment-500342145", +// "issue_url": "https://api.github.com/repos/efoxTeam/flutter-ui/issues/53", +// "id": 500342145, +// "node_id": "MDEyOklzc3VlQ29tbWVudDUwMDM0MjE0NQ==", +// "user": { +// "login": "DIVINER-onlys", +// "id": 35843543, +// "node_id": "MDQ6VXNlcjM1ODQzNTQz", +// "avatar_url": "https://avatars0.githubusercontent.com/u/35843543?v=4", +// "gravatar_id": "", +// "url": "https://api.github.com/users/DIVINER-onlys", +// "html_url": "https://github.com/DIVINER-onlys", +// "followers_url": "https://api.github.com/users/DIVINER-onlys/followers", +// "following_url": "https://api.github.com/users/DIVINER-onlys/following{/other_user}", +// "gists_url": "https://api.github.com/users/DIVINER-onlys/gists{/gist_id}", +// "starred_url": "https://api.github.com/users/DIVINER-onlys/starred{/owner}{/repo}", +// "subscriptions_url": "https://api.github.com/users/DIVINER-onlys/subscriptions", +// "organizations_url": "https://api.github.com/users/DIVINER-onlys/orgs", +// "repos_url": "https://api.github.com/users/DIVINER-onlys/repos", +// "events_url": "https://api.github.com/users/DIVINER-onlys/events{/privacy}", +// "received_events_url": "https://api.github.com/users/DIVINER-onlys/received_events", +// "type": "User", +// "site_admin": false +// }, +// "created_at": "2019-06-10T08:51:54Z", +// "updated_at": "2019-06-10T08:51:54Z", +// "author_association": "NONE", +// "body": "ooooo" +// } +// ] +// } \ No newline at end of file diff --git a/lib/store/objects/user_info.dart b/lib/store/objects/user_info.dart index e5bdcbd..7c6af85 100644 --- a/lib/store/objects/user_info.dart +++ b/lib/store/objects/user_info.dart @@ -1,4 +1,4 @@ -import 'dart:convert'; +//import 'dart:convert'; class UserInfo extends Object { String login; diff --git a/lib/utils/appVersion.dart b/lib/utils/appVersion.dart index 6a894b7..eeb865b 100644 --- a/lib/utils/appVersion.dart +++ b/lib/utils/appVersion.dart @@ -61,6 +61,7 @@ class AppVersion { url: 'https://raw.githubusercontent.com/efoxTeam/flutter-ui/master/version.json', ); + // ignore: missing_return return await response.then((resp) { if (resp.data != null) { var data = json.decode(resp.data); diff --git a/lib/widget/scrollview/gridview/demo_custom.dart b/lib/widget/scrollview/gridview/demo_custom.dart index dd9f239..f677390 100644 --- a/lib/widget/scrollview/gridview/demo_custom.dart +++ b/lib/widget/scrollview/gridview/demo_custom.dart @@ -23,6 +23,7 @@ class Index extends StatelessWidget { // 滚动时回调函数 semanticIndexCallback: (widget, index) { print('index $index'); + return index; }, ), // 数量滚滚动限制,类似GridView.count diff --git a/lib/widget/scrollview/nestedscrollview/index.dart b/lib/widget/scrollview/nestedscrollview/index.dart index c512c2e..84593a8 100644 --- a/lib/widget/scrollview/nestedscrollview/index.dart +++ b/lib/widget/scrollview/nestedscrollview/index.dart @@ -5,7 +5,7 @@ import 'demo.dart' as Demo; class Index extends StatefulWidget { static String title = 'NestedScrollView'; static String mdUrl = 'docs/widget/scrollview/nestedscrollview/index.md'; - static String originCodeUrl = 'https://docs.flutter.io/flutter/widgets/Scrollbar-class.html'; + static String originCodeUrl = 'https://docs.flutter.io/flutter/material/Scrollbar-class.html'; @override _IndexState createState() => new _IndexState(); diff --git a/lib/widget/scrollview/scrollbar/index.dart b/lib/widget/scrollview/scrollbar/index.dart index cbc9ce7..9af7dc7 100644 --- a/lib/widget/scrollview/scrollbar/index.dart +++ b/lib/widget/scrollview/scrollbar/index.dart @@ -5,7 +5,7 @@ import 'demo.dart' as Demo; class Index extends StatefulWidget { static String title = 'Scrollbar'; static String mdUrl = 'docs/widget/scrollview/scrollbar/index.md'; - static String originCodeUrl = 'https://docs.flutter.io/flutter/widgets/Scrollbar-class.html'; + static String originCodeUrl = 'https://docs.flutter.io/flutter/material/Scrollbar-class.html'; @override _IndexState createState() => new _IndexState(); diff --git a/locale/en.json b/locale/en.json index d65bb5e..f5ab3e0 100644 --- a/locale/en.json +++ b/locale/en.json @@ -1,6 +1,9 @@ { "title_component": "Components", "title_my": "My", + "title_comment": "comment", + "title_comment_detials": "Comment details", + "title_library": "library", "common": { "login": "Sign In", "logout": "Logout" @@ -13,7 +16,9 @@ "compProgress": "Components Progress", "success": "Success To Change ", "theme": "Select Theme", - "version": "Version" + "version": "Version", + "doc_online": "document online", + "doc_offline": "document offline" }, "mine": { "loadNetwork": "Load Network Document Resources", diff --git a/locale/zh.json b/locale/zh.json index 6c22b44..f091824 100644 --- a/locale/zh.json +++ b/locale/zh.json @@ -1,6 +1,9 @@ { "title_component": "组件", "title_my": "我的", + "title_comment": "评论", + "title_comment_detials": "评论详情", + "title_library": "第三方库", "common": { "login": "登录", "logout": "退出" @@ -13,7 +16,9 @@ "compProgress": "组件进度", "success": "切换成功", "theme": "选择主题", - "version": "版本" + "version": "版本", + "doc_online": "线上文档", + "doc_offline": "离线文档" }, "mine": { "loadNetwork": "网络优良,可选择加载线上文档资源", diff --git a/pubspec.yaml b/pubspec.yaml index 8fa2882..90e4af4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ description: A new Flutter project. # 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.2+1 +version: 1.0.3+1 environment: sdk: ">=2.1.0 <3.0.0" @@ -26,6 +26,7 @@ dependencies: pull_to_refresh: ^1.1.6 #加载更多 shared_preferences: ^0.4.2 #简单数据存储 provide: ^1.0.2 #数据管理层 + provider: ^3.1.0 dio: ^2.0.14 cached_network_image: ^0.5.1 intl: ^0.15.7 @@ -40,6 +41,7 @@ dependencies: flutter_downloader: ^1.1.6 open_file: ^2.0.1+1 permission_handler: ^3.0.0 + oktoast: ^2.2.0 dev_dependencies: flutter_test: diff --git a/readme.md b/readme.md index e970cc5..a9042ee 100644 --- a/readme.md +++ b/readme.md @@ -1,88 +1,10 @@ -# Flutter UI v1.0.2 +# Flutter UI v1.0.3 +[项目正筹划新一轮更新欢迎建议OR提ISSUE](https://github.com/YYFlutter/flutter-ui/issues/55) -> YY Flutter 开发者社区 - -[![License](https://img.shields.io/github/issues/YYFlutter/flutter-ui.svg)](https://jitpack.io/#YYFlutter/flutter-ui) -[![Stars](https://img.shields.io/github/stars/YYFlutter/flutter-ui.svg)](https://jitpack.io/#YYFlutter/flutter-ui) -[![Stars](https://img.shields.io/github/forks/YYFlutter/flutter-ui.svg)](https://jitpack.io/#YYFlutter/flutter-ui) -[![Forks](https://img.shields.io/github/issues/YYFlutter/flutter-ui.svg)](https://jitpack.io/#YYFlutter/flutter-ui) - -## 社区功能介绍 -+ [团队介绍]() -+ FlutterUI Demo -+ 文章类 - + Flutter系列教程 - + Flutter实战组件集锦 - + 其它推文 -+ 插件类 - + [Flutter-animation-set 动画插件](https://github.com/YYFlutter/flutter-animation-set) -+ [安卓包下载](https://github.com/YYFlutter/flutter-ui/releases/download/v1.0.2/app-release.apk) -+ 社区互动与交流 - - -## FlutterUI Demo预览 - - - -### Flutter系列教程 -| 文章 | 文章状态 | 作者 | 变更日志 | -| --- | --- | --- | --- | -| | 进行中 | | | -| | 进行中 | | | -| | 进行中 | | | - - - -### Flutter实战组件集锦 -#### 弹层【集锦】 -| 文章 | 文章状态 | 作者 | 变更日志 | -| --- | --- | --- | --- | -| 透明弹窗背景 | 进行中 | | | -| 确认框 | 进行中 | | | -| 聊天输入框 | 进行中 | | | -| | 进行中 | | | -| | 进行中 | | | -| | 已完成 | | | - - -#### 列表【集锦】 -| 文章 | 文章状态 | 作者 | 变更日志 | -| --- | --- | --- | --- | -| 上下拉加载 | 进行中 | | | -| | 进行中 | | | - - -#### 列表【导航】 -| 文章 | 文章状态 | 作者 | 变更日志 | -| --- | --- | --- | --- | -| 顶部透明 | 进行中 | | | -| | 进行中 | | | - - -#### 列表【适配方案】 -| 文章 | 文章状态 | 作者 | 变更日志 | -| --- | --- | --- | --- | -| 适配iphonex底部 | 进行中 | | | -| | 进行中 | | | - -### 其它推文 -| 文章 | 文章状态 | 作者 | 变更日志 | -| --- | --- | --- | --- | -| [Flutter UI APP 低调上线](https://juejin.im/post/5c90514e6fb9a070c859029c) | 已完成 | [ken](https://github.com/ckken) | 2019/03/19 | -| [Flutter 接入 firebase 快速构建应用](https://juejin.im/post/5c90514e6fb9a070c859029c) | 已完成 | [ken](https://github.com/ckken) | 2019/03/19 | -| [Flutter UI 1.0.2落地与优化小结](https://juejin.im/post/5c95e691f265da610c06905c) | 已完成 | [ken](https://github.com/ckken) | 2019/03/23 | -| [Flutter 全局弹窗](https://juejin.im/post/5c9f2c37518825609415d11d) | 已完成 | [wanwu](https://github.com/wanwusangzhi) | 2019/03/30 | -| [Flutter UI使用Provide实现主题切换](https://juejin.im/post/5ca5e240f265da30c1725021) | 已完成 | [DIVINER-onlys](https://github.com/DIVINER-onlys) | 2019/04/04 | -| [Flutter provide ProvideMulti](https://juejin.im/post/5cc685835188252e8925f056) | 已完成 | [wanwu](https://github.com/wanwusangzhi) | 2019/03/23 | -| [以$t形式使用flutter多语言](https://juejin.im/post/5cdb8adee51d453acc60162c) | 已完成 | [DIVINER-onlys](https://github.com/DIVINER-onlys) | 2019/05/15 | -| [Flutter Provider 3.0实战教程](https://juejin.im/post/5d2c19c6e51d4558936aa11c) | 已完成 | [DIVINER-onlys](https://github.com/DIVINER-onlys) | 2019/07/15 | - - -## apk 下载 -![安卓包下载](https://github.com/YYFlutter/flutter-ui/blob/master/readme/apk.png?raw=true) -[安卓包下载](https://github.com/YYFlutter/flutter-ui/releases/download/v1.0.2/app-release.apk) ## 项目相关 ++ [项目官方文章](https://github.com/YYFlutter/flutter-article) ++ [项目开发规范](https://github.com/YYFlutter/flutter-article/blob/master/lint/v1.0.md) + [apk包历史版本](https://github.com/YYFlutter/flutter-ui/releases) + [组件开发进度](readme/widget_progress.md) + [贡献PR参考](readme/pr.md) diff --git a/version.json b/version.json index 84184c0..bcfa2c4 100644 --- a/version.json +++ b/version.json @@ -1 +1 @@ -{"version":"1.0.2"} +{"version":"1.0.3"}