app_widget.dart 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import 'package:app_flowy/workspace/application/app/app_bloc.dart';
  2. import 'package:app_flowy/workspace/application/app/app_watch_bloc.dart';
  3. import 'package:app_flowy/workspace/presentation/app/view_list.dart';
  4. import 'package:app_flowy/workspace/presentation/widgets/menu/menu_list.dart';
  5. import 'package:app_flowy/workspace/presentation/widgets/menu/menu_size.dart';
  6. import 'package:app_flowy/startup/startup.dart';
  7. import 'package:expandable/expandable.dart';
  8. import 'package:flowy_infra/size.dart';
  9. import 'package:flowy_infra_ui/widget/error_page.dart';
  10. import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart';
  11. import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
  12. import 'package:flutter/material.dart';
  13. import 'package:flutter_bloc/flutter_bloc.dart';
  14. import 'package:dartz/dartz.dart';
  15. class AppWidget extends MenuItem {
  16. final App app;
  17. const AppWidget(this.app, {Key? key}) : super(key: key);
  18. @override
  19. Widget build(BuildContext context) {
  20. return MultiBlocProvider(
  21. providers: [
  22. BlocProvider<AppBloc>(create: (context) {
  23. final appBloc = getIt<AppBloc>(param1: app.id);
  24. appBloc.add(const AppEvent.initial());
  25. return appBloc;
  26. }),
  27. BlocProvider<AppWatchBloc>(create: (context) {
  28. final watchBloc = getIt<AppWatchBloc>(param1: app.id);
  29. watchBloc.add(const AppWatchEvent.started());
  30. return watchBloc;
  31. }),
  32. ],
  33. child: BlocBuilder<AppWatchBloc, AppWatchState>(
  34. builder: (context, state) {
  35. final child = state.map(
  36. initial: (_) => BlocBuilder<AppBloc, AppState>(
  37. builder: (context, state) {
  38. return ViewList(state.views);
  39. },
  40. ),
  41. loadViews: (s) => ViewList(some(s.views)),
  42. loadFail: (s) => FlowyErrorPage(s.error.toString()),
  43. );
  44. return expandableWrapper(context, child);
  45. },
  46. ),
  47. );
  48. }
  49. ExpandableNotifier expandableWrapper(BuildContext context, Widget child) {
  50. return ExpandableNotifier(
  51. child: ScrollOnExpand(
  52. scrollOnExpand: true,
  53. scrollOnCollapse: false,
  54. child: Card(
  55. clipBehavior: Clip.antiAlias,
  56. child: Column(
  57. children: <Widget>[
  58. ExpandablePanel(
  59. theme: const ExpandableThemeData(
  60. headerAlignment: ExpandablePanelHeaderAlignment.center,
  61. tapBodyToExpand: false,
  62. tapBodyToCollapse: false,
  63. iconPadding: EdgeInsets.zero,
  64. hasIcon: false,
  65. ),
  66. header: AppHeader(app),
  67. expanded: Padding(
  68. padding: EdgeInsets.only(left: Sizes.iconMed),
  69. child: child,
  70. ),
  71. collapsed: const SizedBox(),
  72. ),
  73. ],
  74. ),
  75. ),
  76. ),
  77. );
  78. }
  79. @override
  80. MenuItemType get type => MenuItemType.app;
  81. }
  82. class AppHeader extends StatelessWidget {
  83. final App app;
  84. const AppHeader(
  85. this.app, {
  86. Key? key,
  87. }) : super(key: key);
  88. @override
  89. Widget build(BuildContext context) {
  90. return Container(
  91. color: Colors.white,
  92. child: Padding(
  93. padding: EdgeInsets.symmetric(vertical: Insets.m),
  94. child: Row(
  95. mainAxisAlignment: MainAxisAlignment.center,
  96. crossAxisAlignment: CrossAxisAlignment.center,
  97. children: [
  98. ExpandableIcon(
  99. theme: ExpandableThemeData(
  100. expandIcon: Icons.arrow_right,
  101. collapseIcon: Icons.arrow_drop_down,
  102. iconColor: Colors.black,
  103. iconSize: HomeMenuSize.collapseIconSize,
  104. iconPadding: EdgeInsets.zero,
  105. hasIcon: false,
  106. ),
  107. ),
  108. Expanded(
  109. child: Text(app.name),
  110. ),
  111. SizedBox(
  112. height: HomeMenuSize.createViewButtonSize,
  113. child: createViewPopupMenu(context),
  114. ),
  115. ],
  116. ),
  117. ),
  118. );
  119. }
  120. Widget createViewPopupMenu(BuildContext context) {
  121. return PopupMenuButton(
  122. iconSize: 24,
  123. tooltip: 'create new view',
  124. icon: const Icon(Icons.add),
  125. padding: EdgeInsets.zero,
  126. onSelected: (viewType) => _createView(viewType as ViewType, context),
  127. itemBuilder: (context) => menuItemBuilder());
  128. }
  129. List<PopupMenuEntry> menuItemBuilder() {
  130. return ViewType.values
  131. .where((element) => element != ViewType.Blank)
  132. .map((ty) {
  133. return PopupMenuItem<ViewType>(
  134. value: ty,
  135. child: Row(
  136. children: <Widget>[Text(ty.name)],
  137. ));
  138. }).toList();
  139. }
  140. void _createView(ViewType viewType, BuildContext context) {
  141. context.read<AppBloc>().add(AppEvent.createView("New view", "", viewType));
  142. }
  143. }