diff --git a/assets/flutter.db b/assets/flutter.db index 20942d5..f72fcea 100644 Binary files a/assets/flutter.db and b/assets/flutter.db differ diff --git a/lib/app/res/cons.dart b/lib/app/res/cons.dart index 050fa7e..1e89dfb 100644 --- a/lib/app/res/cons.dart +++ b/lib/app/res/cons.dart @@ -3,7 +3,7 @@ import 'package:flutter_unit/app/style/TolyIcon.dart'; import 'package:flutter_unit/components/permanent/code/highlighter_style.dart'; class Cons { - static String version = 'V1.0.0'; + static String version = 'V1.1.0'; static const MENU_INFO = ["关于", "帮助", "问题反馈"]; //菜单栏 static const ICONS_MAP = { diff --git a/lib/app/router.dart b/lib/app/router.dart index 04b7ade..abbbb72 100644 --- a/lib/app/router.dart +++ b/lib/app/router.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_unit/views/pages/about/about_me_page.dart'; import 'package:flutter_unit/views/pages/about/about_app_page.dart'; +import 'package:flutter_unit/views/pages/collect/category_show.dart'; import 'package:flutter_unit/views/pages/collect/collect_page.dart'; import 'package:flutter_unit/views/pages/search/serach_page.dart'; import 'package:flutter_unit/views/pages/setting/code_style_setting.dart'; @@ -33,6 +34,9 @@ class Router { static const String code_style_setting = 'CodeStyleSettingPage'; static const String item_style_setting = 'ItemStyleSettingPage'; + + static const String category_show = 'CategoryShow'; + static const String attr = 'AttrUnitPage'; static const String bug = 'BugUnitPage'; static const String paint = 'PaintUnitPage'; @@ -75,6 +79,9 @@ class Router { case about_me: return Right2LeftRouter(child: AboutMePage()); + case category_show: + return Right2LeftRouter(child: CategoryShow(model: settings.arguments,)); + default: return MaterialPageRoute( builder: (_) => Scaffold( diff --git a/lib/app/utils/Toast.dart b/lib/app/utils/Toast.dart index 054b566..67f5017 100644 --- a/lib/app/utils/Toast.dart +++ b/lib/app/utils/Toast.dart @@ -3,10 +3,11 @@ import 'package:flutter/material.dart'; class Toast { static toast(BuildContext context, String msg, - {duration = const Duration(milliseconds: 600)}) { + {duration = const Duration(milliseconds: 600),SnackBarAction action}) { Scaffold.of(context).showSnackBar(SnackBar( content: Text(msg), duration: duration, + action: action, backgroundColor: Theme.of(context).primaryColor, )); } diff --git a/lib/blocs/category/category_bloc.dart b/lib/blocs/category/category_bloc.dart index f20272a..bf342bf 100644 --- a/lib/blocs/category/category_bloc.dart +++ b/lib/blocs/category/category_bloc.dart @@ -43,6 +43,10 @@ class CategoryBloc extends Bloc { await repository.deleteCategory(event.id); add(EventLoadCategory()); } + if (event is EventToggleWidget) { + await repository.toggleCategory(event.categoryId,event.widgetId); + add(EventLoadCategory()); + } if (event is EventAddCategory) { var categoryPo = CategoryPo( @@ -62,6 +66,7 @@ class CategoryBloc extends Bloc { } } + // if (event is EventAddCategory) { // var collectPo = CategoryPo( // name: event.name, diff --git a/lib/blocs/category/category_event.dart b/lib/blocs/category/category_event.dart index cc060bc..f8c1043 100644 --- a/lib/blocs/category/category_event.dart +++ b/lib/blocs/category/category_event.dart @@ -15,6 +15,16 @@ class EventLoadCategory extends CategoryEvent{ List get props => []; } +class EventToggleWidget extends CategoryEvent{ + final int widgetId; + final int categoryId; + + EventToggleWidget({this.widgetId, this.categoryId}); + + @override + List get props => [widgetId,categoryId]; +} + class EventDeleteCategory extends CategoryEvent{ final int id; diff --git a/lib/blocs/category/category_state.dart b/lib/blocs/category/category_state.dart index a8f66bf..4f7ca4c 100644 --- a/lib/blocs/category/category_state.dart +++ b/lib/blocs/category/category_state.dart @@ -1,5 +1,6 @@ import 'package:equatable/equatable.dart'; import 'package:flutter_unit/model/category_model.dart'; +import 'package:flutter_unit/model/widget_model.dart'; /// create by 张风捷特烈 on 2020-04-21 /// contact me by email 1981462002@qq.com diff --git a/lib/blocs/category_widget/category_widget_bloc.dart b/lib/blocs/category_widget/category_widget_bloc.dart new file mode 100644 index 0000000..cf0cdfb --- /dev/null +++ b/lib/blocs/category_widget/category_widget_bloc.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_unit/blocs/category/category_bloc.dart'; +import 'package:flutter_unit/blocs/category/category_event.dart'; +import 'package:flutter_unit/repositories/itf/category_repository.dart'; + +import 'category_widget_event.dart'; +import 'category_widget_state.dart'; + +/// create by 张风捷特烈 on 2020-04-21 +/// contact me by email 1981462002@qq.com +/// 说明: + +class CategoryWidgetBloc + extends Bloc { + final CategoryBloc categoryBloc; + + CategoryWidgetBloc({@required this.categoryBloc}) { + print('CategoryBloc'); + } + + CategoryRepository get repository => categoryBloc.repository; + + @override + CategoryWidgetState get initialState => CategoryWidgetEmptyState(); //初始状态 + + @override + Stream mapEventToState( + CategoryWidgetEvent event) async* { + if (event is EventLoadCategoryWidget) { + final widgets = + await repository.loadCategoryWidgets(categoryId: event.categoryId); + yield widgets.isNotEmpty + ? CategoryWidgetLoadedState(widgets) + : CategoryWidgetEmptyState(); + categoryBloc.add(EventLoadCategory()); + } + + if (event is EventToggleCategoryWidget) { + await repository.toggleCategory(event.categoryId, event.widgetId); + add(EventLoadCategoryWidget(event.categoryId)); + } + } +} diff --git a/lib/blocs/category_widget/category_widget_event.dart b/lib/blocs/category_widget/category_widget_event.dart new file mode 100644 index 0000000..6313aae --- /dev/null +++ b/lib/blocs/category_widget/category_widget_event.dart @@ -0,0 +1,55 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; + +/// create by 张风捷特烈 on 2020-04-21 +/// contact me by email 1981462002@qq.com +/// 说明: + +abstract class CategoryWidgetEvent extends Equatable{ + @override + List get props => []; +} + +//class EventLoadCategory extends CategoryWidgetEvent{ +// @override +// List get props => []; +//} + +class EventLoadCategoryWidget extends CategoryWidgetEvent{ + final int categoryId; + + EventLoadCategoryWidget(this.categoryId); + + @override + List get props => [categoryId]; +} + +class EventToggleCategoryWidget extends CategoryWidgetEvent{ + final int categoryId; + final int widgetId; + + EventToggleCategoryWidget(this.categoryId,this.widgetId); + + @override + List get props => [categoryId,widgetId]; +} + +//class EventDeleteCategory extends CategoryWidgetEvent{ +// final int id; +// +// EventDeleteCategory({@required this.id}); +// +// @override +// List get props => [id]; +//} +// +//class EventAddCategory extends CategoryWidgetEvent{ +// final String name; +// final String info; +// final String color; +// +// EventAddCategory({@required this.name, this.info, this.color}); +// +// @override +// List get props => [name,info,color]; +//} diff --git a/lib/blocs/category_widget/category_widget_state.dart b/lib/blocs/category_widget/category_widget_state.dart new file mode 100644 index 0000000..991a00d --- /dev/null +++ b/lib/blocs/category_widget/category_widget_state.dart @@ -0,0 +1,32 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter_unit/model/category_model.dart'; +import 'package:flutter_unit/model/widget_model.dart'; + +/// create by 张风捷特烈 on 2020-04-21 +/// contact me by email 1981462002@qq.com +/// 说明: + +class CategoryWidgetState extends Equatable{ + @override + List get props => []; + +} + + +class CategoryWidgetLoadedState extends CategoryWidgetState { + final List widgets; + + CategoryWidgetLoadedState(this.widgets); + + List get props => [widgets]; + +} + +class CategoryWidgetEmptyState extends CategoryWidgetState{ + List get props => []; +} + + +class AddCategoryFailed extends CategoryWidgetState{ + +} diff --git a/lib/components/permanent/circle_text.dart b/lib/components/permanent/circle_text.dart index a548b57..8918a9e 100644 --- a/lib/components/permanent/circle_text.dart +++ b/lib/components/permanent/circle_text.dart @@ -45,7 +45,7 @@ class CircleText extends StatelessWidget { color: backgroundColor??Color(0xffD8F5FF), ), child: Text( - text.substring(0, 2), + text.length>2?text.substring(0, 2):text, style: TextStyle( fontSize: fontSize, color: color, diff --git a/lib/main.dart b/lib/main.dart index 9821bba..17b9a74 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,7 +1,6 @@ - - import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_unit/blocs/category_widget/category_widget_bloc.dart'; import 'package:flutter_unit/storage/app_storage.dart'; import 'package:flutter_unit/views/pages/splash/unit_splash.dart'; @@ -56,10 +55,9 @@ class BlocWrapper extends StatelessWidget { BlocProvider( create: (_) => DetailBloc(repository: repository)), - - BlocProvider(create: (_) { - return CategoryBloc(repository: categoryRepo)..add(EventLoadCategory()); - } ), + BlocProvider( + create: (_) => + CategoryBloc(repository: categoryRepo)..add(EventLoadCategory())), BlocProvider( create: (_) => @@ -75,19 +73,23 @@ class FlutterApp extends StatelessWidget { @override Widget build(BuildContext context) { return BlocBuilder(builder: (_, state) { - return MaterialApp( - title: 'Flutter Demo', - debugShowCheckedModeBanner: false, - onGenerateRoute: Router.generateRoute, - theme: ThemeData( - primarySwatch: state.themeColor, - fontFamily: state.fontFamily, - ), - home: + return BlocProvider( + create: (_) => CategoryWidgetBloc( + categoryBloc: BlocProvider.of(context)), + child: MaterialApp( + title: 'Flutter Demo', + debugShowCheckedModeBanner: false, + onGenerateRoute: Router.generateRoute, + theme: ThemeData( + primarySwatch: state.themeColor, + fontFamily: state.fontFamily, + ), + home: // NavPage() - UnitSplash() + UnitSplash() // UnitNavigation(), - ); + ), + ); }); } } diff --git a/lib/model/category_model.dart b/lib/model/category_model.dart index 5e0861a..f0d79c9 100644 --- a/lib/model/category_model.dart +++ b/lib/model/category_model.dart @@ -35,7 +35,7 @@ class CategoryModel extends Equatable{ info: po.info, createDate: DateFormat('yyyy-MM-dd HH:mm').format(po.created), imageCover: po.image, - count: 10, + count: po.count, color: ColorUtils.parse(po.color), ); } @@ -50,4 +50,11 @@ class CategoryModel extends Equatable{ count, color, ]; + + @override + String toString() { + return 'CategoryModel{id: $id, name: $name, info: $info, createDate: $createDate, imageCover: $imageCover, count: $count, color: $color}'; + } + + } \ No newline at end of file diff --git a/lib/repositories/impl/catagory_db_repository.dart b/lib/repositories/impl/catagory_db_repository.dart index 4ffd947..215e6db 100644 --- a/lib/repositories/impl/catagory_db_repository.dart +++ b/lib/repositories/impl/catagory_db_repository.dart @@ -8,7 +8,7 @@ import 'package:flutter_unit/storage/po/widget_po.dart'; /// create by 张风捷特烈 on 2020-04-21 /// contact me by email 1981462002@qq.com -/// 说明: +/// 说明: class CategoryDbRepository implements CategoryRepository { final AppStorage storage; @@ -20,43 +20,44 @@ class CategoryDbRepository implements CategoryRepository { } @override - Future addCategory(CategoryPo categoryPo) async{ + Future addCategory(CategoryPo categoryPo) async { var success = await _collectDao.insert(categoryPo); return success != -1; } @override - Future check(int categoryId, int widgetId) async{ + Future check(int categoryId, int widgetId) async { return await _collectDao.existWidgetInCollect(categoryId, widgetId); - } @override - Future deleteCategory(int id) async{ + Future deleteCategory(int id) async { await _collectDao.deleteCollect(id); } @override - Future> loadCategories() async{ + Future> loadCategories() async { var data = await _collectDao.queryAll(); var collects = data.map((e) => CategoryPo.fromJson(e)).toList(); return collects.map(CategoryModel.fromPo).toList(); } @override - Future> loadCategoryWidgets({int categoryId = 0}) async{ - var rawData = await _collectDao.loadCollectWidgets(1); + Future> loadCategoryWidgets({int categoryId = 0}) async { + var rawData = await _collectDao.loadCollectWidgets(categoryId); var widgets = rawData.map((e) => WidgetPo.fromJson(e)).toList(); return widgets.map(WidgetModel.fromPo).toList(); } @override - Future toggleCategory(int id) async{ - return await _collectDao.toggleCollectDefault(id); - + Future toggleCategory(int categoryId, int widgetId) async { + return await _collectDao.toggleCollect( categoryId, widgetId); } - + @override + Future> getCategoryByWidget(int widgetId) async { + return await _collectDao.categoryWidgetIds(widgetId); + } // // @override @@ -70,4 +71,4 @@ class CategoryDbRepository implements CategoryRepository { // Future checkCollected(int collectId, int widgetId) async { // // } -} \ No newline at end of file +} diff --git a/lib/repositories/itf/category_repository.dart b/lib/repositories/itf/category_repository.dart index 0b4e04b..24c701d 100644 --- a/lib/repositories/itf/category_repository.dart +++ b/lib/repositories/itf/category_repository.dart @@ -8,7 +8,7 @@ import 'package:flutter_unit/storage/po/category_po.dart'; abstract class CategoryRepository { - Future toggleCategory(int id); + Future toggleCategory(int categoryId, int widgetId); Future check(int categoryId,int widgetId); @@ -20,5 +20,8 @@ abstract class CategoryRepository { Future addCategory(CategoryPo categoryPo); Future deleteCategory(int id); + Future> getCategoryByWidget(int widgetId); + + } \ No newline at end of file diff --git a/lib/storage/dao/category_dao.dart b/lib/storage/dao/category_dao.dart index cdc68ac..161c880 100644 --- a/lib/storage/dao/category_dao.dart +++ b/lib/storage/dao/category_dao.dart @@ -45,7 +45,6 @@ class CategoryDao { } Future addWidget(int categoryId,int widgetId,) async { - //插入方法 final db = await _db; String addSql = //插入数据 "INSERT INTO " @@ -71,15 +70,35 @@ class CategoryDao { } Future>> queryAll() async { - //插入方法 final db = await _db; - return await db.rawQuery("SELECT * " - "FROM category ORDER BY priority DESC,created DESC"); + var data = await db.rawQuery( + "SELECT c.id,c.name,c.info,c.color,c.image,c.created,c.updated,c.priority,COUNT(cw.categoryId) as `count`" + "FROM category AS c " + "LEFT JOIN category_widget AS cw " + "ON c.id = cw.categoryId GROUP BY c.id " + "ORDER BY priority DESC,created DESC", + []); + print(data); + return data; } - Future deleteCollect(int id) async { - //插入方法 + Future> categoryWidgetIds(int id) async { final db = await _db; + var data = await db.rawQuery( + "SELECT categoryId FROM `category_widget`" + "WHERE widgetId = ?", + [id]); + return data.toList().map((e)=>e["categoryId"]).toList(); + } + + + + Future deleteCollect(int id) async { + final db = await _db; + await db.execute( + "DELETE FROM category_widget " + "WHERE categoryId = ?", + [id]); return await db.execute( "DELETE FROM category " "WHERE id = ?", @@ -127,7 +146,8 @@ class CategoryDao { Future>> loadCollectWidgets(int categoryId) async{ String querySql = //插入数据 "SELECT * FROM widget " - "WHERE id IN (SELECT widgetId FROM category_widget WHERE categoryId = ?)"; + "WHERE id IN (SELECT widgetId FROM category_widget WHERE categoryId = ?) " + "ORDER BY lever DESC"; final db = await _db; return await db.rawQuery(querySql,[categoryId]); diff --git a/lib/storage/po/category_po.dart b/lib/storage/po/category_po.dart index 6901ea6..09890d1 100644 --- a/lib/storage/po/category_po.dart +++ b/lib/storage/po/category_po.dart @@ -24,6 +24,7 @@ class CategoryPo extends Equatable { final DateTime created; final DateTime updated; final String image; + final int count; final int priority; const CategoryPo( @@ -32,6 +33,7 @@ class CategoryPo extends Equatable { this.color = '#FFF2F2F2', this.created, this.updated, + this.count = 0, this.priority = 0, this.info = '这里什么都没有...', this.image = ''}); @@ -44,16 +46,18 @@ class CategoryPo extends Equatable { created: DateTime.parse(map["created"]), image: map["image"], priority: map["priority"], + count: map["count"], updated: DateTime.parse(map["updated"]), info: map["info"]); } + @override String toString() { - return 'CollectPo{id: $id, name: $name, color: $color, info: $info, created: $created, updated: $updated, image: $image, priority: $priority}'; + return 'CategoryPo{id: $id, name: $name, color: $color, info: $info, created: $created, updated: $updated, image: $image, count: $count, priority: $priority}'; } @override List get props => - [id, name, color, created, image, info, updated, priority]; + [id, name, color, created, image, info, updated, priority,count]; } diff --git a/lib/views/common/unit_drawer_header.dart b/lib/views/common/unit_drawer_header.dart new file mode 100644 index 0000000..e0373b4 --- /dev/null +++ b/lib/views/common/unit_drawer_header.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.dart'; + +/// create by 张风捷特烈 on 2020-04-22 +/// contact me by email 1981462002@qq.com +/// 说明: + +class UnitDrawerHeader extends StatelessWidget { + final Color color; + + + UnitDrawerHeader({this.color}); + + @override + Widget build(BuildContext context) { + return DrawerHeader( + padding: EdgeInsets.only(top: 10, left: 15), + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/wy_300x200_filter.jpg'), + fit: BoxFit.cover), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Wrap( + spacing: 10, + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + FlutterLogo( + colors: Colors.orange, + size: 35, + ), + Text( + 'Flutter Unit', + style: TextStyle(fontSize: 24, color: Colors.white, shadows: [ + Shadow( + color: Colors.black, + offset: Offset(1, 1), + blurRadius: 3) + ]), + ), + ], + ), + SizedBox( + height: 15, + ), + Text( + 'The Unity Of Flutter, The Unity Of Coder.', + style: TextStyle(fontSize: 15, color: Colors.white, shadows: [ + Shadow(color: color, offset: Offset(.5, .5), blurRadius: 1) + ]), + ), + SizedBox( + height: 5, + ), + Text( + 'Flutter的联合,编程者的联合。', + style: TextStyle(fontSize: 15, color: Colors.white, shadows: [ + Shadow(color: color, offset: Offset(.5, .5), blurRadius: 1) + ]), + ), + SizedBox( + height: 10, + ), + Row( + children: [ + Spacer( + flex: 5, + ), + Text( + '—— 张风捷特烈', + style: TextStyle(fontSize: 15, color: Colors.white, shadows: [ + Shadow( + color: Colors.orangeAccent, + offset: Offset(.5, .5), + blurRadius: 1) + ]), + ), + Spacer( + flex: 1, + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/views/pages/collect/category_page.dart b/lib/views/pages/collect/category_page.dart index 2ce94ab..3429ea6 100644 --- a/lib/views/pages/collect/category_page.dart +++ b/lib/views/pages/collect/category_page.dart @@ -4,6 +4,8 @@ import 'package:flutter_unit/app/router.dart'; import 'package:flutter_unit/blocs/category/category_bloc.dart'; import 'package:flutter_unit/blocs/category/category_event.dart'; import 'package:flutter_unit/blocs/category/category_state.dart'; +import 'package:flutter_unit/blocs/category_widget/category_widget_bloc.dart'; +import 'package:flutter_unit/blocs/category_widget/category_widget_event.dart'; import 'package:flutter_unit/blocs/collect/collect_bloc.dart'; import 'package:flutter_unit/blocs/collect/collect_event.dart'; import 'package:flutter_unit/blocs/detail/detail_bloc.dart'; @@ -69,7 +71,7 @@ class CategoryPage extends StatelessWidget { } _toDetailPage(BuildContext context, CategoryModel model) { -// BlocProvider.of(context).add(FetchWidgetDetail(model)); -// Navigator.pushNamed(context, Router.widget_detail, arguments: model); + BlocProvider.of(context).add(EventLoadCategoryWidget(model.id)); + Navigator.pushNamed(context, Router.category_show, arguments: model); } } diff --git a/lib/views/pages/collect/category_show.dart b/lib/views/pages/collect/category_show.dart new file mode 100644 index 0000000..950508a --- /dev/null +++ b/lib/views/pages/collect/category_show.dart @@ -0,0 +1,158 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_star/flutter_star.dart'; +import 'package:flutter_unit/app/router.dart'; +import 'package:flutter_unit/blocs/category_widget/category_widget_bloc.dart'; +import 'package:flutter_unit/blocs/category_widget/category_widget_event.dart'; +import 'package:flutter_unit/blocs/category_widget/category_widget_state.dart'; +import 'package:flutter_unit/blocs/detail/detail_bloc.dart'; +import 'package:flutter_unit/blocs/detail/detail_event.dart'; +import 'package:flutter_unit/components/permanent/circle_image.dart'; +import 'package:flutter_unit/components/permanent/circle_text.dart'; +import 'package:flutter_unit/components/permanent/feedback_widget.dart'; +import 'package:flutter_unit/model/category_model.dart'; +import 'package:flutter_unit/model/widget_model.dart'; +import 'package:flutter_unit/views/items/techno_widget_list_item.dart'; + +/// create by 张风捷特烈 on 2020-04-22 +/// contact me by email 1981462002@qq.com +/// 说明: + +class CategoryShow extends StatelessWidget { + final CategoryModel model; + + CategoryShow({this.model}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text(model.name)), + body: BlocBuilder(builder: (_, state) { + if (state is CategoryWidgetLoadedState) { + return _buildWidgetList(state.widgets); + } + return Container(); + }), + ); + } + + Widget _buildWidgetList(List widgets) { + return ListView.separated( + separatorBuilder: (_, index) => Divider(height: 1,), + itemBuilder: (context, index) => Dismissible( + direction: DismissDirection.endToStart, + key: ValueKey(widgets[index].id), + background: Container( + padding: EdgeInsets.only(right: 20), + alignment: Alignment.centerRight, + color: Colors.red, + child: Icon(CupertinoIcons.delete_solid,color: Colors.white,size: 30,), + ), + onDismissed: (v){ + BlocProvider.of(context) + .add(EventToggleCategoryWidget(model.id,widgets[index].id)); + }, + child: Container( + margin: EdgeInsets.symmetric(horizontal: 15, vertical: 8), + child: FeedbackWidget( + duration: Duration(milliseconds: 200), + onPressed: () => _toDetailPage(context, widgets[index]), + child: SimpleWidgetItem( + data: widgets[index], + )), + ), + ), + itemCount: widgets.length); + } + + _toDetailPage(BuildContext context, WidgetModel model) async { + BlocProvider.of(context).add(FetchWidgetDetail(model)); + Navigator.pushNamed(context, Router.widget_detail, arguments: model); + } +} + +class SimpleWidgetItem extends StatelessWidget { + final WidgetModel data; + + SimpleWidgetItem({this.data}); + + @override + Widget build(BuildContext context) { + return Container( + color: Colors.transparent, + height: 75, + child: Row( + children: [ + SizedBox(width: 10,), + Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _buildLeading(), + + StarScore( + star: Star(emptyColor: Colors.white, size: 12, fillColor: data.color), + score: data.lever, + ), + ], + ), + SizedBox(width: 20,), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _buildTitle(), + _buildSummary() + ], + ), + ) + ], + ), + ); + + } + + Widget _buildTitle() { + return Text(data.name, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 17, + fontWeight: FontWeight.bold, + shadows: [Shadow(color: Colors.white, offset: Offset(.3, .3))])); + } + + Widget _buildLeading() => Padding( + padding: const EdgeInsets.only(left: 5, right: 5), + child: Hero( + tag: "hero_widget_image_${data.id}", + child: data.image == null + ? Material( + color: Colors.transparent, + child: CircleText( + text: data.name, + size: 50, + color: data.color, + ), + ) + : CircleImage( + image: data.image, + size: 50, + ), + ), + ); + + Widget _buildSummary() { + return Container( + child: Text( + data.info, + maxLines: 2, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Colors.grey[600], + fontSize: 14, + shadows: [Shadow(color: Colors.white, offset: Offset(.5, .5))]), + ), + ); + } +} diff --git a/lib/views/pages/collect/collect_page.dart b/lib/views/pages/collect/collect_page.dart index 085160e..0bd8860 100644 --- a/lib/views/pages/collect/collect_page.dart +++ b/lib/views/pages/collect/collect_page.dart @@ -22,7 +22,7 @@ class CollectPage extends StatelessWidget { childAspectRatio: 1 / 0.5, ); - final _tabs = ['默认收藏', '收藏集录']; + final _tabs = ['收藏集录','默认收藏', ]; @override @@ -47,11 +47,11 @@ class CollectPage extends StatelessWidget { padding: EdgeInsets.only(top: 150-30.0-10), child: TabBarView( children: [ + CategoryPage(), BlocBuilder( builder: (_, state) => CustomScrollView( slivers: [_buildContent(context, state)], )), - CategoryPage() ], ), ), diff --git a/lib/views/pages/collect/home_right_drawer.dart b/lib/views/pages/collect/home_right_drawer.dart index 4b2fc2d..e7311db 100644 --- a/lib/views/pages/collect/home_right_drawer.dart +++ b/lib/views/pages/collect/home_right_drawer.dart @@ -10,19 +10,20 @@ import 'package:flutter_unit/blocs/collect/collect_bloc.dart'; import 'package:flutter_unit/blocs/collect/collect_event.dart'; import 'package:flutter_unit/components/permanent/circle.dart'; import 'package:flutter_unit/components/project/color_chooser.dart'; +import 'package:flutter_unit/views/common/unit_drawer_header.dart'; import 'package:flutter_unit/views/pages/collect/InputButton.dart'; import 'package:flutter_unit/views/pages/collect/edit_panel.dart'; -class HoneRightDrawer extends StatefulWidget { +class HomeRightDrawer extends StatefulWidget { final Color color; - HoneRightDrawer({this.color}); + HomeRightDrawer({this.color}); @override - _HoneRightDrawerState createState() => _HoneRightDrawerState(); + _HomeRightDrawerState createState() => _HomeRightDrawerState(); } -class _HoneRightDrawerState extends State { +class _HomeRightDrawerState extends State { String name; String color; String info; @@ -38,7 +39,7 @@ class _HoneRightDrawerState extends State { Widget _buildChild(BuildContext context) => Container( color: widget.color.withAlpha(33), child: ListView(padding: EdgeInsets.zero, children: [ - _buildDrawerHeader(widget.color), + UnitDrawerHeader(color:widget.color), _buildTitle(context), Padding( padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8), @@ -77,79 +78,6 @@ class _HoneRightDrawerState extends State { ]), ); - Widget _buildDrawerHeader(Color color) => DrawerHeader( - padding: EdgeInsets.only(top: 10, left: 15), - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('assets/images/wy_300x200_filter.jpg'), - fit: BoxFit.cover), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Wrap( - spacing: 10, - crossAxisAlignment: WrapCrossAlignment.center, - children: [ - FlutterLogo( - colors: Colors.orange, - size: 35, - ), - Text( - 'Flutter Unit', - style: TextStyle(fontSize: 24, color: Colors.white, shadows: [ - Shadow( - color: Colors.black, - offset: Offset(1, 1), - blurRadius: 3) - ]), - ), - ], - ), - SizedBox( - height: 15, - ), - Text( - 'The Unity Of Flutter, The Unity Of Coder.', - style: TextStyle(fontSize: 15, color: Colors.white, shadows: [ - Shadow(color: color, offset: Offset(.5, .5), blurRadius: 1) - ]), - ), - SizedBox( - height: 5, - ), - Text( - 'Flutter的联合,编程者的联合。', - style: TextStyle(fontSize: 15, color: Colors.white, shadows: [ - Shadow(color: color, offset: Offset(.5, .5), blurRadius: 1) - ]), - ), - SizedBox( - height: 10, - ), - Row( - children: [ - Spacer( - flex: 5, - ), - Text( - '—— 张风捷特烈', - style: TextStyle(fontSize: 15, color: Colors.white, shadows: [ - Shadow( - color: Colors.orangeAccent, - offset: Offset(.5, .5), - blurRadius: 1) - ]), - ), - Spacer( - flex: 1, - ), - ], - ), - ], - ), - ); - Widget _buildTitle(BuildContext context) { return Padding( padding: const EdgeInsets.only(top: 5.0, bottom: 8), diff --git a/lib/views/pages/detail/category_end_drawer.dart b/lib/views/pages/detail/category_end_drawer.dart new file mode 100644 index 0000000..4112f6b --- /dev/null +++ b/lib/views/pages/detail/category_end_drawer.dart @@ -0,0 +1,181 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_unit/app/style/unit_color.dart'; +import 'package:flutter_unit/app/utils/color_utils.dart'; +import 'package:flutter_unit/blocs/category/category_bloc.dart'; +import 'package:flutter_unit/blocs/category/category_event.dart'; +import 'package:flutter_unit/blocs/category/category_state.dart'; +import 'package:flutter_unit/blocs/category_widget/category_widget_bloc.dart'; +import 'package:flutter_unit/blocs/category_widget/category_widget_event.dart'; +import 'package:flutter_unit/components/permanent/circle.dart'; +import 'package:flutter_unit/components/permanent/feedback_widget.dart'; +import 'package:flutter_unit/components/permanent/panel.dart'; +import 'package:flutter_unit/components/project/color_chooser.dart'; +import 'package:flutter_unit/model/category_model.dart'; +import 'package:flutter_unit/model/widget_model.dart'; +import 'package:flutter_unit/repositories/itf/category_repository.dart'; +import 'package:flutter_unit/views/common/unit_drawer_header.dart'; +import 'package:flutter_unit/views/pages/collect/InputButton.dart'; +import 'package:flutter_unit/views/pages/collect/edit_panel.dart'; + +/// create by 张风捷特烈 on 2020-04-22 +/// contact me by email 1981462002@qq.com +/// 说明: + +class CategoryEndDrawer extends StatelessWidget { + final WidgetModel widget; + + CategoryEndDrawer({this.widget}); + + @override + Widget build(BuildContext context) { + return Drawer( + child: _buildChild(context), + ); + } + + Widget _buildChild(BuildContext context) => Container( + child: ListView(padding: EdgeInsets.zero, children: [ + UnitDrawerHeader(color: Theme.of(context).primaryColor), + Padding( + padding: const EdgeInsets.all(10.0), + child: Row( + children: [ + Circle( + color: widget.color, + ), + SizedBox( + width: 10, + ), + Text(widget.name) + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15.0), + child: Panel( + child: Text( + widget.info, + style: TextStyle(color: Colors.grey, shadows: [ + Shadow( + color: Colors.white, offset: Offset(.5, .5), blurRadius: .5) + ]), + ), + ), + ), + Divider(), + _buildTitle(context), + Divider(), + CategoryInfo(widget.id) + ])); + + Widget _buildTitle(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(top: 5.0, bottom: 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Circle( + color: Theme.of(context).primaryColor, + radius: 5, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Text( + '当前组件收藏情况', + style: TextStyle(fontSize: 16, shadows: [ + Shadow( + color: Colors.white, offset: Offset(.5, .5), blurRadius: 1) + ]), + ), + ), + Circle( + color: Theme.of(context).primaryColor, + radius: 5, + ), + ], + ), + ); + } +} + +class CategoryInfo extends StatefulWidget { + final int id; + + CategoryInfo(this.id); + + @override + _CategoryInfoState createState() => _CategoryInfoState(); +} + +class _CategoryInfoState extends State { + List categoryIds = []; + List _categories = []; + +// var + + @override + void didChangeDependencies() { + _loadCategoryIds(); + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + return _buildCategory(); + } + + Widget _buildCategory() { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Wrap( + alignment: WrapAlignment.spaceBetween, + spacing: 5, +// runSpacing: 10, + children: categories.map((e) => _buildItem(e)).toList(), + ), + ); + } + + Widget _buildItem(CategoryModel category) { + bool inHere = categoryIds.contains(category.id); + return FilterChip( + backgroundColor: Theme.of(context).primaryColor.withAlpha(33), +// backgroundColor: category.color.withAlpha(88), + selectedColor: Colors.orange.withAlpha(120), + shadowColor: Theme.of(context).primaryColor, + elevation: 1, + avatar: Circle( + radius: 13, + color: category.color, + ), + selected: inHere, + label: Text(category.name), + onSelected: (v) async { + await repository.toggleCategory(category.id, widget.id); + _loadCategoryIds(); + BlocProvider.of(context).add(EventLoadCategoryWidget(category.id)); + }); + } + + CategoryRepository get repository => + BlocProvider.of(context).repository; + + List get categories { + var state = BlocProvider.of(context).state; + if (state is CategoryLoadedState) { + _categories = state.categories; + } + return _categories; + } + + void _loadCategoryIds() async { + categoryIds = await repository.getCategoryByWidget(widget.id); + print(categoryIds); + if(mounted) + setState(() { + + }); + } +} diff --git a/lib/views/pages/detail/widget_detail_page.dart b/lib/views/pages/detail/widget_detail_page.dart index 77edac6..8a80e70 100644 --- a/lib/views/pages/detail/widget_detail_page.dart +++ b/lib/views/pages/detail/widget_detail_page.dart @@ -17,6 +17,7 @@ import 'package:flutter_unit/components/permanent/panel.dart'; import 'package:flutter_unit/components/project/widget_node_panel.dart'; import 'package:flutter_unit/model/node_model.dart'; import 'package:flutter_unit/model/widget_model.dart'; +import 'package:flutter_unit/views/pages/detail/category_end_drawer.dart'; import 'package:flutter_unit/views/widgets/widgets_map.dart'; class WidgetDetailPage extends StatefulWidget { @@ -29,9 +30,8 @@ class WidgetDetailPage extends StatefulWidget { } class _WidgetDetailPageState extends State { - WidgetModel _model; - - List _models=[]; + List _models = []; + bool openBottom = false; @override void deactivate() { @@ -48,26 +48,35 @@ class _WidgetDetailPageState extends State { @override Widget build(BuildContext context) { return WillPopScope( - onWillPop: () async{ + onWillPop: () async { _models.removeLast(); - if(_models.length>0){ + if (_models.length > 0) { setState(() { - BlocProvider.of(context).add(FetchWidgetDetail(_models.last)); + BlocProvider.of(context) + .add(FetchWidgetDetail(_models.last)); }); return false; - }else{ + } else { return true; } }, child: Scaffold( + endDrawer: CategoryEndDrawer(widget: _models.last,), appBar: AppBar( title: Text(_models.last.name), actions: [ - IconButton(icon:Icon( Icons.home), onPressed: (){ - Navigator.of(context).pop(); - }), - buildCollectButton(_models.last, context), - + Builder(builder: (ctx)=>GestureDetector( + onLongPress: (){ + Scaffold.of(ctx).openEndDrawer(); + }, + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Icon(Icons.home), + ), + onTap: () { + Navigator.of(ctx).pop(); + })), + _buildCollectButton(_models.last, context), ], ), body: SingleChildScrollView( @@ -118,13 +127,21 @@ class _WidgetDetailPageState extends State { ); } - Widget buildCollectButton(WidgetModel model, BuildContext context) { + Widget _buildCollectButton(WidgetModel model, BuildContext context) { //监听 CollectBloc 伺机弹出toast return BlocListener( listener: (ctx, st) { bool collected = st.widgets.contains(model); - Toast.toast(ctx, - collected ? "收藏【${model.name}】组件成功!" : "已取消【${model.name}】组件收藏!"); + var msg = + collected ? "收藏【${model.name}】组件成功!" : "已取消【${model.name}】组件收藏!"; + + Toast.toast(ctx, msg, + duration: Duration(milliseconds: collected?1500:600), + action: collected + ? SnackBarAction( + textColor: Colors.white, label: '收藏夹管理', onPressed: () { + Scaffold.of(ctx).openEndDrawer(); + }): null,); }, child: FeedbackWidget( onPressed: () => BlocProvider.of(context) @@ -181,7 +198,8 @@ class _WidgetDetailPageState extends State { children: links .map((e) => ActionChip( onPressed: () { - BlocProvider.of(context).add(FetchWidgetDetail(e)); + BlocProvider.of(context) + .add(FetchWidgetDetail(e)); setState(() { _models.add(e); }); diff --git a/lib/views/pages/setting/home_drawer.dart b/lib/views/pages/home/home_drawer.dart similarity index 60% rename from lib/views/pages/setting/home_drawer.dart rename to lib/views/pages/home/home_drawer.dart index 86614dc..4f5349e 100644 --- a/lib/views/pages/setting/home_drawer.dart +++ b/lib/views/pages/home/home_drawer.dart @@ -1,14 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_unit/app/router.dart'; import 'package:flutter_unit/app/style/TolyIcon.dart'; -import 'package:flutter_unit/blocs/collect/collect_bloc.dart'; -import 'package:flutter_unit/blocs/collect/collect_event.dart'; -import 'package:flutter_unit/blocs/global/global_bloc.dart'; -import 'package:flutter_unit/blocs/global/global_state.dart'; -import 'package:flutter_unit/blocs/widgets/home_bloc.dart'; -import 'package:flutter_unit/blocs/widgets/home_state.dart'; import 'package:flutter_unit/components/flutter/no_div_expansion_tile.dart'; +import 'package:flutter_unit/views/common/unit_drawer_header.dart'; /// create by 张风捷特烈 on 2020-03-26 /// contact me by email 1981462002@qq.com @@ -26,13 +20,12 @@ class HomeDrawer extends StatelessWidget { child: _buildChild(context), ); } - Widget _buildChild(BuildContext context) => Container( color: color.withAlpha(33), child: ListView( padding: EdgeInsets.zero, children: [ - _buildDrawerHeader(color), + UnitDrawerHeader(color:color), ListTile( leading: Icon( TolyIcon.icon_them, @@ -145,78 +138,6 @@ class HomeDrawer extends StatelessWidget { ], ); - Widget _buildDrawerHeader(Color color) => DrawerHeader( - padding: EdgeInsets.only(top: 10, left: 15), - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('assets/images/wy_300x200_filter.jpg'), - fit: BoxFit.cover), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Wrap( - spacing: 10, - crossAxisAlignment: WrapCrossAlignment.center, - children: [ - FlutterLogo( - colors: Colors.orange, - size: 35, - ), - Text( - 'Flutter Unit', - style: TextStyle(fontSize: 24, color: Colors.white, shadows: [ - Shadow( - color: Colors.black, - offset: Offset(1, 1), - blurRadius: 3) - ]), - ), - ], - ), - SizedBox( - height: 15, - ), - Text( - 'The Unity Of Flutter, The Unity Of Coder.', - style: TextStyle(fontSize: 15, color: Colors.white, shadows: [ - Shadow(color: color, offset: Offset(.5, .5), blurRadius: 1) - ]), - ), - SizedBox( - height: 5, - ), - Text( - 'Flutter的联合,编程者的联合。', - style: TextStyle(fontSize: 15, color: Colors.white, shadows: [ - Shadow(color: color, offset: Offset(.5, .5), blurRadius: 1) - ]), - ), - SizedBox( - height: 10, - ), - Row( - children: [ - Spacer( - flex: 5, - ), - Text( - '—— 张风捷特烈', - style: TextStyle(fontSize: 15, color: Colors.white, shadows: [ - Shadow( - color: Colors.orangeAccent, - offset: Offset(.5, .5), - blurRadius: 1) - ]), - ), - Spacer( - flex: 1, - ), - ], - ), - ], - ), - ); Widget _nextIcon(BuildContext context) => Icon(Icons.chevron_right, color: Theme.of(context).primaryColor); diff --git a/lib/views/pages/navigation/unit_navigation.dart b/lib/views/pages/navigation/unit_navigation.dart index 52531f2..f298fc1 100644 --- a/lib/views/pages/navigation/unit_navigation.dart +++ b/lib/views/pages/navigation/unit_navigation.dart @@ -11,7 +11,7 @@ import 'package:flutter_unit/views/pages/collect/home_right_drawer.dart'; import 'package:flutter_unit/views/pages/navigation/unit_bottom_bar.dart'; import '../collect/category_page.dart'; import '../home/home_page.dart'; -import '../setting/home_drawer.dart'; +import '../home/home_drawer.dart'; class UnitNavigation extends StatefulWidget { @override @@ -39,7 +39,7 @@ class _UnitNavigationState extends State { builder: (_, state) => Scaffold( drawer: HomeDrawer(color:state.homeColor), //左滑页 - endDrawer: HoneRightDrawer(color: state.homeColor,), + endDrawer: HomeRightDrawer(color: state.homeColor,), //右滑页 floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, diff --git a/lib/views/widgets/ProxyWidget/InheritedWidget/SliderTheme.dart b/lib/views/widgets/ProxyWidget/InheritedWidget/SliderTheme.dart index 025a223..c105776 100644 --- a/lib/views/widgets/ProxyWidget/InheritedWidget/SliderTheme.dart +++ b/lib/views/widgets/ProxyWidget/InheritedWidget/SliderTheme.dart @@ -111,25 +111,24 @@ class _CustomThumbShape extends SliderComponentShape { ); @override - void paint( - PaintingContext context, - Offset thumbCenter, { - Animation activationAnimation, - Animation enableAnimation, - bool isDiscrete, - TextPainter labelPainter, - RenderBox parentBox, - SliderThemeData sliderTheme, - TextDirection textDirection, - double value, - }) { + void paint(PaintingContext context, Offset center, + {Animation activationAnimation, + Animation enableAnimation, + bool isDiscrete, + TextPainter labelPainter, + RenderBox parentBox, + SliderThemeData sliderTheme, + TextDirection textDirection, + double value, + double textScaleFactor, + Size sizeWithOverflow}) { final Canvas canvas = context.canvas; final ColorTween colorTween = ColorTween( begin: sliderTheme.disabledThumbColor, end: sliderTheme.thumbColor, ); final double size = _thumbSize * sizeTween.evaluate(enableAnimation); - final Path thumbPath = _downTriangle(size, thumbCenter); + final Path thumbPath = _downTriangle(size, center); canvas.drawPath( thumbPath, Paint()..color = colorTween.evaluate(enableAnimation)); } @@ -169,18 +168,17 @@ class _CustomValueIndicatorShape extends SliderComponentShape { ); @override - void paint( - PaintingContext context, - Offset thumbCenter, { - Animation activationAnimation, - Animation enableAnimation, - bool isDiscrete, - TextPainter labelPainter, - RenderBox parentBox, - SliderThemeData sliderTheme, - TextDirection textDirection, - double value, - }) { + void paint(PaintingContext context, Offset center, + {Animation activationAnimation, + Animation enableAnimation, + bool isDiscrete, + TextPainter labelPainter, + RenderBox parentBox, + SliderThemeData sliderTheme, + TextDirection textDirection, + double value, + double textScaleFactor, + Size sizeWithOverflow}) { final Canvas canvas = context.canvas; final ColorTween enableColor = ColorTween( begin: sliderTheme.disabledThumbColor, @@ -193,7 +191,7 @@ class _CustomValueIndicatorShape extends SliderComponentShape { final double size = _indicatorSize * sizeTween.evaluate(enableAnimation); final Offset slideUpOffset = Offset(0.0, -slideUpTween.evaluate(activationAnimation)); - final Path thumbPath = _upTriangle(size, thumbCenter + slideUpOffset); + final Path thumbPath = _upTriangle(size, center + slideUpOffset); final Color paintColor = enableColor .evaluate(enableAnimation) .withAlpha((255.0 * activationAnimation.value).round()); @@ -202,15 +200,15 @@ class _CustomValueIndicatorShape extends SliderComponentShape { Paint()..color = paintColor, ); canvas.drawLine( - thumbCenter, - thumbCenter + slideUpOffset, + center, + center + slideUpOffset, Paint() ..color = paintColor ..style = PaintingStyle.stroke ..strokeWidth = 2.0); labelPainter.paint( canvas, - thumbCenter + + center + slideUpOffset + Offset(-labelPainter.width / 2.0, -labelPainter.height - 4.0)); } diff --git a/lib/views/widgets/widgets_map.dart b/lib/views/widgets/widgets_map.dart index e099d4a..0be1f05 100644 --- a/lib/views/widgets/widgets_map.dart +++ b/lib/views/widgets/widgets_map.dart @@ -1,5 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_unit/views/widgets/StatefulWidget/AnimatedWidget/SlideTransition.dart'; import 'ProxyWidget/InheritedWidget/ButtonTheme.dart'; import 'ProxyWidget/InheritedWidget/DefaultTextStyle.dart'; import 'ProxyWidget/InheritedWidget/DividerTheme.dart'; @@ -545,6 +546,10 @@ class WidgetsMap { return [ CustomAlignTransition(), ]; + case "SlideTransition": + return [ + CustomSlideTransition(), + ]; case "DecoratedBoxTransition": return [ CustomDecoratedBoxTransition(), diff --git a/pubspec.yaml b/pubspec.yaml index 396f0e5..2fa5cc9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: A new Flutter application. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.0.0+1 +version: 1.1.0+1 environment: sdk: ">=2.3.0 <3.0.0"