home_screen.dart 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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/material.dart';
  11. import 'package:flutter_bloc/flutter_bloc.dart';
  12. import 'package:styled_widget/styled_widget.dart';
  13. import '../widgets/edit_pannel/edit_pannel.dart';
  14. import 'home_layout.dart';
  15. import 'home_stack.dart';
  16. import 'menu/menu.dart';
  17. class HomeScreen extends StatefulWidget {
  18. final UserProfilePB user;
  19. final CurrentWorkspaceSettingPB workspaceSetting;
  20. const HomeScreen(this.user, this.workspaceSetting, {Key? key}) : super(key: key);
  21. @override
  22. State<HomeScreen> createState() => _HomeScreenState();
  23. }
  24. class _HomeScreenState extends State<HomeScreen> {
  25. ViewPB? initialView;
  26. @override
  27. void initState() {
  28. super.initState();
  29. }
  30. @override
  31. void didUpdateWidget(covariant HomeScreen oldWidget) {
  32. initialView = null;
  33. super.didUpdateWidget(oldWidget);
  34. }
  35. @override
  36. Widget build(BuildContext context) {
  37. return MultiBlocProvider(
  38. providers: [
  39. BlocProvider<HomeBloc>(
  40. create: (context) {
  41. return HomeBloc(widget.user, widget.workspaceSetting)..add(const HomeEvent.initial());
  42. },
  43. ),
  44. ],
  45. child: Scaffold(
  46. body: BlocListener<HomeBloc, HomeState>(
  47. listenWhen: (p, c) => p.unauthorized != c.unauthorized,
  48. listener: (context, state) {
  49. if (state.unauthorized) {
  50. Log.error("Push to login screen when user token was invalid");
  51. }
  52. },
  53. child: BlocBuilder<HomeBloc, HomeState>(
  54. buildWhen: (previous, current) => previous != current,
  55. builder: (context, state) {
  56. final collapasedNotifier = getIt<HomeStackManager>().collapsedNotifier;
  57. collapasedNotifier.addPublishListener((isCollapsed) {
  58. context.read<HomeBloc>().add(HomeEvent.forceCollapse(isCollapsed));
  59. });
  60. return FlowyContainer(
  61. Theme.of(context).colorScheme.surface,
  62. // Colors.white,
  63. child: _buildBody(state),
  64. );
  65. },
  66. ),
  67. ),
  68. ),
  69. );
  70. }
  71. Widget _buildBody(HomeState state) {
  72. return LayoutBuilder(
  73. builder: (BuildContext context, BoxConstraints constraints) {
  74. final layout = HomeLayout(context, constraints, state.forceCollapse);
  75. const homeStack = HomeStack();
  76. final menu = _buildHomeMenu(
  77. layout: layout,
  78. context: context,
  79. state: state,
  80. );
  81. final editPannel = _buildEditPannel(
  82. homeState: state,
  83. layout: layout,
  84. context: context,
  85. );
  86. const bubble = QuestionBubble();
  87. return _layoutWidgets(
  88. layout: layout,
  89. homeStack: homeStack,
  90. homeMenu: menu,
  91. editPannel: editPannel,
  92. bubble: bubble,
  93. );
  94. },
  95. );
  96. }
  97. Widget _buildHomeMenu({required HomeLayout layout, required BuildContext context, required HomeState state}) {
  98. final workspaceSetting = state.workspaceSetting;
  99. if (initialView == null && workspaceSetting.hasLatestView()) {
  100. initialView = workspaceSetting.latestView;
  101. final plugin = makePlugin(
  102. pluginType: initialView!.pluginType,
  103. data: initialView,
  104. );
  105. getIt<HomeStackManager>().setPlugin(plugin);
  106. }
  107. HomeMenu homeMenu = HomeMenu(
  108. user: widget.user,
  109. workspaceSetting: workspaceSetting,
  110. collapsedNotifier: getIt<HomeStackManager>().collapsedNotifier,
  111. );
  112. final latestView = workspaceSetting.hasLatestView() ? workspaceSetting.latestView : null;
  113. if (getIt<MenuSharedState>().latestOpenView == null) {
  114. /// AppFlowy will open the view that the last time the user opened it. The _buildHomeMenu will get called when AppFlowy's screen resizes. So we only set the latestOpenView when it's null.
  115. getIt<MenuSharedState>().latestOpenView = latestView;
  116. }
  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 _layoutWidgets({
  139. required HomeLayout layout,
  140. required Widget homeMenu,
  141. required Widget homeStack,
  142. required Widget editPannel,
  143. required Widget bubble,
  144. }) {
  145. return Stack(
  146. children: [
  147. homeMenu
  148. .animatedPanelX(
  149. closeX: -layout.menuWidth,
  150. isClosed: !layout.showMenu,
  151. )
  152. .positioned(left: 0, top: 0, width: layout.menuWidth, bottom: 0, animate: true)
  153. .animate(layout.animDuration, Curves.easeOut),
  154. homeStack
  155. .constrained(minWidth: 500)
  156. .positioned(left: layout.homePageLOffset, right: layout.homePageROffset, bottom: 0, top: 0, animate: true)
  157. .animate(layout.animDuration, Curves.easeOut),
  158. bubble
  159. .positioned(
  160. right: 20,
  161. bottom: 16,
  162. animate: true,
  163. )
  164. .animate(layout.animDuration, Curves.easeOut),
  165. editPannel
  166. .animatedPanelX(
  167. duration: layout.animDuration.inMilliseconds * 0.001,
  168. closeX: layout.editPannelWidth,
  169. isClosed: !layout.showEditPannel,
  170. )
  171. .positioned(right: 0, top: 0, bottom: 0, width: layout.editPannelWidth),
  172. ],
  173. );
  174. }
  175. }