home_screen.dart 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. import 'package:app_flowy/plugin/plugin.dart';
  2. import 'package:app_flowy/workspace/application/home/home_bloc.dart';
  3. import 'package:app_flowy/workspace/presentation/widgets/edit_pannel/pannel_animation.dart';
  4. import 'package:app_flowy/workspace/presentation/widgets/float_bubble/question_bubble.dart';
  5. import 'package:app_flowy/startup/startup.dart';
  6. import 'package:flowy_sdk/log.dart';
  7. import 'package:flowy_infra_ui/style_widget/container.dart';
  8. import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart' show UserProfilePB;
  9. import 'package:flowy_sdk/protobuf/flowy-folder/protobuf.dart';
  10. import 'package:flutter/gestures.dart';
  11. import 'package:flutter/material.dart';
  12. import 'package:flutter_bloc/flutter_bloc.dart';
  13. import 'package:styled_widget/styled_widget.dart';
  14. import '../widgets/edit_pannel/edit_pannel.dart';
  15. import 'home_layout.dart';
  16. import 'home_stack.dart';
  17. import 'menu/menu.dart';
  18. class HomeScreen extends StatefulWidget {
  19. final UserProfilePB user;
  20. final CurrentWorkspaceSettingPB workspaceSetting;
  21. const HomeScreen(this.user, this.workspaceSetting, {Key? key}) : super(key: key);
  22. @override
  23. State<HomeScreen> createState() => _HomeScreenState();
  24. }
  25. class _HomeScreenState extends State<HomeScreen> {
  26. ViewPB? initialView;
  27. @override
  28. void initState() {
  29. super.initState();
  30. }
  31. @override
  32. void didUpdateWidget(covariant HomeScreen oldWidget) {
  33. initialView = null;
  34. super.didUpdateWidget(oldWidget);
  35. }
  36. @override
  37. Widget build(BuildContext context) {
  38. return MultiBlocProvider(
  39. providers: [
  40. BlocProvider<HomeBloc>(
  41. create: (context) {
  42. return HomeBloc(widget.user, widget.workspaceSetting)..add(const HomeEvent.initial());
  43. },
  44. ),
  45. ],
  46. child: Scaffold(
  47. body: BlocListener<HomeBloc, HomeState>(
  48. listenWhen: (p, c) => p.unauthorized != c.unauthorized,
  49. listener: (context, state) {
  50. if (state.unauthorized) {
  51. Log.error("Push to login screen when user token was invalid");
  52. }
  53. },
  54. child: BlocBuilder<HomeBloc, HomeState>(
  55. buildWhen: (previous, current) => previous != current,
  56. builder: (context, state) {
  57. final collapasedNotifier = getIt<HomeStackManager>().collapsedNotifier;
  58. collapasedNotifier.addPublishListener((isCollapsed) {
  59. context.read<HomeBloc>().add(HomeEvent.forceCollapse(isCollapsed));
  60. });
  61. return FlowyContainer(
  62. Theme.of(context).colorScheme.surface,
  63. // Colors.white,
  64. child: _buildBody(state),
  65. );
  66. },
  67. ),
  68. ),
  69. ),
  70. );
  71. }
  72. Widget _buildBody(HomeState state) {
  73. return LayoutBuilder(
  74. builder: (BuildContext context, BoxConstraints constraints) {
  75. final layout = HomeLayout(context, constraints, state.forceCollapse);
  76. const homeStack = HomeStack();
  77. final menu = _buildHomeMenu(
  78. layout: layout,
  79. context: context,
  80. state: state,
  81. );
  82. final homeMenuResizer = _buildHomeMenuResizer(context: context);
  83. final editPannel = _buildEditPannel(
  84. homeState: state,
  85. layout: layout,
  86. context: context,
  87. );
  88. const bubble = QuestionBubble();
  89. return _layoutWidgets(
  90. layout: layout,
  91. homeStack: homeStack,
  92. homeMenu: menu,
  93. editPannel: editPannel,
  94. bubble: bubble,
  95. homeMenuResizer: homeMenuResizer,
  96. );
  97. },
  98. );
  99. }
  100. Widget _buildHomeMenu({required HomeLayout layout, required BuildContext context, required HomeState state}) {
  101. final workspaceSetting = state.workspaceSetting;
  102. if (initialView == null && workspaceSetting.hasLatestView()) {
  103. initialView = workspaceSetting.latestView;
  104. final plugin = makePlugin(
  105. pluginType: initialView!.pluginType,
  106. data: initialView,
  107. );
  108. getIt<HomeStackManager>().setPlugin(plugin);
  109. }
  110. HomeMenu homeMenu = HomeMenu(
  111. user: widget.user,
  112. workspaceSetting: workspaceSetting,
  113. collapsedNotifier: getIt<HomeStackManager>().collapsedNotifier,
  114. );
  115. final latestView = workspaceSetting.hasLatestView() ? workspaceSetting.latestView : null;
  116. getIt<MenuSharedState>().latestOpenView = latestView;
  117. return FocusTraversalGroup(child: RepaintBoundary(child: homeMenu));
  118. }
  119. Widget _buildEditPannel({required HomeState homeState, required BuildContext context, required HomeLayout layout}) {
  120. final homeBloc = context.read<HomeBloc>();
  121. return BlocBuilder<HomeBloc, HomeState>(
  122. buildWhen: (previous, current) => previous.pannelContext != current.pannelContext,
  123. builder: (context, state) {
  124. return state.pannelContext.fold(
  125. () => const SizedBox(),
  126. (pannelContext) => FocusTraversalGroup(
  127. child: RepaintBoundary(
  128. child: EditPannel(
  129. pannelContext: pannelContext,
  130. onEndEdit: () => homeBloc.add(const HomeEvent.dismissEditPannel()),
  131. ),
  132. ),
  133. ),
  134. );
  135. },
  136. );
  137. }
  138. Widget _buildHomeMenuResizer({
  139. required BuildContext context,
  140. }) {
  141. return MouseRegion(
  142. cursor: SystemMouseCursors.resizeLeftRight,
  143. child: GestureDetector(
  144. dragStartBehavior: DragStartBehavior.down,
  145. onPanUpdate: ((details) {
  146. context.read<HomeBloc>().add(HomeEvent.editPannelResized(details.delta.dx));
  147. }),
  148. behavior: HitTestBehavior.translucent,
  149. child: SizedBox(
  150. width: 10,
  151. height: MediaQuery.of(context).size.height,
  152. )),
  153. );
  154. }
  155. Widget _layoutWidgets({
  156. required HomeLayout layout,
  157. required Widget homeMenu,
  158. required Widget homeStack,
  159. required Widget editPannel,
  160. required Widget bubble,
  161. required Widget homeMenuResizer,
  162. }) {
  163. return Stack(
  164. children: [
  165. homeMenu
  166. .animatedPanelX(
  167. closeX: -layout.menuWidth,
  168. isClosed: !layout.showMenu,
  169. )
  170. .positioned(left: 0, top: 0, width: layout.menuWidth, bottom: 0, animate: true)
  171. .animate(layout.animDuration, Curves.easeOut),
  172. homeStack
  173. .constrained(minWidth: 500)
  174. .positioned(left: layout.homePageLOffset, right: layout.homePageROffset, bottom: 0, top: 0, animate: true)
  175. .animate(layout.animDuration, Curves.easeOut),
  176. homeMenuResizer.positioned(left: layout.homePageLOffset - 5),
  177. bubble
  178. .positioned(
  179. right: 20,
  180. bottom: 16,
  181. animate: true,
  182. )
  183. .animate(layout.animDuration, Curves.easeOut),
  184. editPannel
  185. .animatedPanelX(
  186. duration: layout.animDuration.inMilliseconds * 0.001,
  187. closeX: layout.editPannelWidth,
  188. isClosed: !layout.showEditPannel,
  189. )
  190. .positioned(right: 0, top: 0, bottom: 0, width: layout.editPannelWidth),
  191. ],
  192. );
  193. }
  194. }