Browse Source

rename some widget with prefix Flowy

appflowy 3 years ago
parent
commit
199fbd8873
37 changed files with 338 additions and 191 deletions
  1. 1 0
      app_flowy/lib/workspace/domain/page_stack/page_stack.dart
  2. 17 11
      app_flowy/lib/workspace/presentation/app/app_widget.dart
  3. 1 1
      app_flowy/lib/workspace/presentation/app/view_list.dart
  4. 2 2
      app_flowy/lib/workspace/presentation/doc/doc_page.dart
  5. 2 2
      app_flowy/lib/workspace/presentation/home/home_screen.dart
  6. 9 7
      app_flowy/lib/workspace/presentation/view/view_widget.dart
  7. 4 4
      app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart
  8. 21 24
      app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart
  9. 2 2
      app_flowy/lib/workspace/presentation/widgets/menu/create_app_dialog.dart
  10. 1 1
      app_flowy/lib/workspace/presentation/widgets/menu/menu.dart
  11. 3 8
      app_flowy/lib/workspace/presentation/widgets/menu/menu_new_app.dart
  12. 4 4
      app_flowy/lib/workspace/presentation/widgets/menu/menu_user.dart
  13. 2 2
      app_flowy/packages/flowy_infra_ui/lib/style_widget/bar_title.dart
  14. 2 2
      app_flowy/packages/flowy_infra_ui/lib/style_widget/close_button.dart
  15. 2 2
      app_flowy/packages/flowy_infra_ui/lib/style_widget/container.dart
  16. 27 0
      app_flowy/packages/flowy_infra_ui/lib/style_widget/extension.dart
  17. 7 7
      app_flowy/packages/flowy_infra_ui/lib/style_widget/hover.dart
  18. 5 5
      app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart
  19. 2 2
      app_flowy/packages/flowy_infra_ui/lib/style_widget/image_icon.dart
  20. 4 3
      app_flowy/packages/flowy_infra_ui/lib/style_widget/navigation_list.dart
  21. 2 2
      app_flowy/packages/flowy_infra_ui/lib/style_widget/progress_indicator.dart
  22. 2 2
      app_flowy/packages/flowy_infra_ui/lib/style_widget/text.dart
  23. 6 6
      app_flowy/packages/flowy_infra_ui/lib/style_widget/text_button.dart
  24. 2 2
      app_flowy/packages/flowy_infra_ui/lib/style_widget/text_input.dart
  25. 2 2
      app_flowy/packages/flowy_infra_ui/lib/widget/buttons/secondary_button.dart
  26. 15 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_create.pb.dart
  27. 2 1
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_create.pbjson.dart
  28. 15 0
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pb.dart
  29. 2 1
      app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pbjson.dart
  30. 3 0
      rust-lib/flowy-workspace/src/entities/app/app_create.rs
  31. 3 0
      rust-lib/flowy-workspace/src/entities/view/view_create.rs
  32. 78 40
      rust-lib/flowy-workspace/src/protobuf/model/app_create.rs
  33. 84 46
      rust-lib/flowy-workspace/src/protobuf/model/view_create.rs
  34. 1 0
      rust-lib/flowy-workspace/src/protobuf/proto/app_create.proto
  35. 1 0
      rust-lib/flowy-workspace/src/protobuf/proto/view_create.proto
  36. 1 0
      rust-lib/flowy-workspace/src/sql_tables/app/app_table.rs
  37. 1 0
      rust-lib/flowy-workspace/src/sql_tables/view/view_table.rs

+ 1 - 0
app_flowy/lib/workspace/domain/page_stack/page_stack.dart

@@ -14,6 +14,7 @@ abstract class HomeStackView extends Equatable {
   const HomeStackView({required this.type, required this.title});
 }
 
+// HomePageStack is initialized as singleton to controll the page stack.
 class HomePageStack {
   final PageStackBloc _bloc = PageStackBloc();
   HomePageStack();

+ 17 - 11
app_flowy/lib/workspace/presentation/app/app_widget.dart

@@ -6,8 +6,8 @@ import 'package:app_flowy/startup/startup.dart';
 import 'package:expandable/expandable.dart';
 import 'package:flowy_infra_ui/widget/error_page.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
-import 'package:flowy_infra_ui/style_widget/styled_text_button.dart';
-import 'package:flowy_infra_ui/style_widget/styled_icon_button.dart';
+import 'package:flowy_infra_ui/style_widget/text_button.dart';
+import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
 import 'package:flutter/material.dart';
@@ -17,28 +17,34 @@ import 'package:dartz/dartz.dart';
 class AppWidgetSize {
   static double expandedIconSize = 24;
   static double expandedIconRightSpace = 8;
-
   static double scale = 1;
-
   static double get expandedPadding =>
       expandedIconSize * scale + expandedIconRightSpace;
 }
 
-class AppWidget extends MenuItem {
+class AppWidgetContext {
   final App app;
-  AppWidget(this.app, {Key? key}) : super(key: ValueKey(app.id));
+
+  AppWidgetContext(this.app);
+
+  Key valueKey() => ValueKey("${app.id}${app.version}");
+}
+
+class AppWidget extends MenuItem {
+  final AppWidgetContext appCtx;
+  AppWidget(this.appCtx, {Key? key}) : super(key: appCtx.valueKey());
 
   @override
   Widget build(BuildContext context) {
     return MultiBlocProvider(
       providers: [
         BlocProvider<AppBloc>(create: (context) {
-          final appBloc = getIt<AppBloc>(param1: app.id);
+          final appBloc = getIt<AppBloc>(param1: appCtx.app.id);
           appBloc.add(const AppEvent.initial());
           return appBloc;
         }),
         BlocProvider<AppWatchBloc>(create: (context) {
-          final watchBloc = getIt<AppWatchBloc>(param1: app.id);
+          final watchBloc = getIt<AppWatchBloc>(param1: appCtx.app.id);
           watchBloc.add(const AppWatchEvent.started());
           return watchBloc;
         }),
@@ -75,7 +81,7 @@ class AppWidget extends MenuItem {
                 iconPadding: EdgeInsets.zero,
                 hasIcon: false,
               ),
-              header: AppHeader(app),
+              header: AppHeader(appCtx.app),
               expanded: child,
               collapsed: const SizedBox(),
             ),
@@ -93,7 +99,7 @@ class AppWidget extends MenuItem {
 
     return Padding(
         padding: const EdgeInsets.symmetric(vertical: 8),
-        child: ViewList(views, key: UniqueKey()));
+        child: ViewList(views));
   }
 
   @override
@@ -132,7 +138,7 @@ class AppHeader extends StatelessWidget {
         ),
         HSpace(AppWidgetSize.expandedIconRightSpace),
         Expanded(
-          child: StyledTextButton(
+          child: FlowyTextButton(
             app.name,
             onPressed: () {
               debugPrint('show app document');

+ 1 - 1
app_flowy/lib/workspace/presentation/app/view_list.dart

@@ -9,7 +9,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 
 class ViewList extends StatelessWidget {
   final List<View> views;
-  const ViewList(this.views, {Key? key}) : super(key: key);
+  ViewList(this.views, {Key? key}) : super(key: UniqueKey());
 
   @override
   Widget build(BuildContext context) {

+ 2 - 2
app_flowy/lib/workspace/presentation/doc/doc_page.dart

@@ -6,7 +6,7 @@ import 'package:flowy_infra_ui/widget/error_page.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flowy_infra_ui/style_widget/styled_progress_indicator.dart';
+import 'package:flowy_infra_ui/style_widget/progress_indicator.dart';
 
 class DocPage extends HomeStackWidget {
   const DocPage({Key? key, required DocPageStackView stackView})
@@ -30,7 +30,7 @@ class _DocPageState extends State<DocPage> {
           BlocBuilder<DocWatchBloc, DocWatchState>(builder: (context, state) {
         assert(widget.stackView is DocPageStackView);
         return state.map(
-          loading: (_) => const StyledProgressIndicator(),
+          loading: (_) => const FlowyProgressIndicator(),
           loadDoc: (s) => EditorWdiget(doc: s.doc),
           loadFail: (s) => FlowyErrorPage(s.error.toString()),
         );

+ 2 - 2
app_flowy/lib/workspace/presentation/home/home_screen.dart

@@ -4,7 +4,7 @@ import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
 import 'package:app_flowy/workspace/presentation/widgets/prelude.dart';
 import 'package:app_flowy/startup/startup.dart';
 import 'package:flowy_infra/flowy_logger.dart';
-import 'package:flowy_infra_ui/style_widget/styled_container.dart';
+import 'package:flowy_infra_ui/style_widget/container.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
@@ -30,7 +30,7 @@ class HomeScreen extends StatelessWidget {
         body: BlocBuilder<HomeBloc, HomeState>(
           buildWhen: (previous, current) => previous != current,
           builder: (context, state) {
-            return StyledContainer(
+            return FlowyContainer(
               Theme.of(context).colorScheme.surface,
               // Colors.white,
               child: _buildBody(

+ 9 - 7
app_flowy/lib/workspace/presentation/view/view_widget.dart

@@ -1,5 +1,5 @@
-import 'package:flowy_infra_ui/style_widget/styled_hover.dart';
-import 'package:flowy_infra_ui/style_widget/styled_icon_button.dart';
+import 'package:flowy_infra_ui/style_widget/hover.dart';
+import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
 import 'package:flutter/material.dart';
@@ -15,6 +15,8 @@ class ViewWidgetContext {
     this.view, {
     this.isSelected = false,
   });
+
+  Key valueKey() => ValueKey("${view.id}${view.version}");
 }
 
 typedef OpenViewCallback = void Function(View);
@@ -22,15 +24,15 @@ typedef OpenViewCallback = void Function(View);
 class ViewWidget extends StatelessWidget {
   final ViewWidgetContext viewCtx;
   final OpenViewCallback onOpen;
-  const ViewWidget({Key? key, required this.viewCtx, required this.onOpen})
-      : super(key: key);
+  ViewWidget({Key? key, required this.viewCtx, required this.onOpen})
+      : super(key: viewCtx.valueKey());
 
   @override
   Widget build(BuildContext context) {
     final config = HoverDisplayConfig(hoverColor: Colors.grey.shade200);
     return InkWell(
       onTap: _openView(context),
-      child: StyledHover(
+      child: FlowyHover(
         config: config,
         builder: (context, onHover) => _render(context, onHover, config),
       ),
@@ -65,7 +67,7 @@ class ViewWidget extends StatelessWidget {
     );
 
     if (viewCtx.isSelected) {
-      widget = HoverBackground(child: widget, config: config);
+      widget = FlowyHoverBackground(child: widget, config: config);
     }
 
     return widget;
@@ -79,7 +81,7 @@ class ViewWidget extends StatelessWidget {
     children.add(const Spacer());
     children.add(Align(
       alignment: Alignment.center,
-      child: StyledMore(
+      child: FlowyMoreButton(
         width: hoverWidth,
         onPressed: () {
           debugPrint('show view setting');

+ 4 - 4
app_flowy/lib/workspace/presentation/widgets/edit_pannel/edit_pannel.dart

@@ -3,8 +3,8 @@ import 'package:app_flowy/workspace/domain/edit_context.dart';
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/presentation/home/home_sizes.dart';
 import 'package:dartz/dartz.dart';
-import 'package:flowy_infra_ui/style_widget/styled_bar_title.dart';
-import 'package:flowy_infra_ui/style_widget/styled_close_button.dart';
+import 'package:flowy_infra_ui/style_widget/bar_title.dart';
+import 'package:flowy_infra_ui/style_widget/close_button.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
@@ -54,11 +54,11 @@ class EditPannelTopBar extends StatelessWidget {
         padding: const EdgeInsets.all(8.0),
         child: Row(
           children: [
-            const StyleBarTitle(
+            const FlowyBarTitle(
               title: 'Title',
             ),
             const Spacer(),
-            StyleCloseButton(onPressed: onClose),
+            FlowyCloseButton(onPressed: onClose),
           ],
         ),
       ),

+ 21 - 24
app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart

@@ -5,8 +5,10 @@ import 'package:flowy_infra_ui/widget/rounded_button.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pbenum.dart';
 import 'package:flutter/material.dart';
-import 'package:flowy_infra_ui/style_widget/styled_icon_button.dart';
-import 'package:flowy_infra_ui/style_widget/styled_text.dart';
+import 'package:flowy_infra_ui/style_widget/icon_button.dart';
+// import 'package:flowy_infra_ui/style_widget/styled_navigation_list.dart';
+import 'package:flowy_infra_ui/style_widget/extension.dart';
+import 'package:flowy_infra_ui/style_widget/text.dart';
 
 class HomeTopBar extends StatelessWidget {
   final HomeStackView view;
@@ -16,26 +18,17 @@ class HomeTopBar extends StatelessWidget {
   Widget build(BuildContext context) {
     return SizedBox(
       height: HomeSizes.topBarHeight,
-      child: Container(
-        decoration: BoxDecoration(
-          border: Border(
-            bottom: BorderSide(width: 0.5, color: Colors.grey.shade300),
-          ),
-        ),
-        child: Padding(
-          padding:
-              EdgeInsets.symmetric(horizontal: HomeInsets.topBarTitlePadding),
-          child: Row(
-            crossAxisAlignment: CrossAxisAlignment.center,
-            children: [
-              HomeTitle(title: view.title, type: view.type),
-              const Spacer(),
-              _renderShareButton(),
-              _renderMoreButton(),
-            ],
-          ),
-        ),
-      ),
+      child: Row(
+        crossAxisAlignment: CrossAxisAlignment.center,
+        children: [
+          HomeTitle(title: view.title, type: view.type),
+          const Spacer(),
+          _renderShareButton(),
+          _renderMoreButton(),
+        ],
+      )
+          .padding(horizontal: HomeInsets.topBarTitlePadding)
+          .bottomBorder(color: Colors.grey.shade300),
     );
   }
 
@@ -54,13 +47,17 @@ class HomeTopBar extends StatelessWidget {
   }
 
   Widget _renderMoreButton() {
-    return StyledMore(
+    return FlowyMoreButton(
       width: 24,
       onPressed: () {
         debugPrint('show more');
       },
     );
   }
+
+  Widget _renderNavigationList() {
+    return Container();
+  }
 }
 
 class HomeTitle extends StatelessWidget {
@@ -84,7 +81,7 @@ class HomeTitle extends StatelessWidget {
               height: 15,
               image: assetImageForViewType(type)),
           const HSpace(6),
-          StyledText(title, fontSize: 16),
+          FlowyText(title, fontSize: 16),
         ],
       ),
     );

+ 2 - 2
app_flowy/lib/workspace/presentation/widgets/menu/create_app_dialog.dart

@@ -2,7 +2,7 @@ import 'package:app_flowy/startup/tasks/application_task.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
 import 'package:flowy_infra/theme.dart';
-import 'package:flowy_infra_ui/style_widget/styled_text_input.dart';
+import 'package:flowy_infra_ui/style_widget/text_input.dart';
 import 'package:flowy_infra_ui/widget/buttons/ok_cancel_button.dart';
 import 'package:flowy_infra_ui/widget/dialog/dialog_context.dart';
 import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
@@ -34,7 +34,7 @@ class CreateAppDialogContext extends DialogContext {
             // Container(color: theme.greyWeak.withOpacity(.35), height: 1),
             VSpace(Insets.m * 1.5),
           ],
-          StyledFormTextInput(
+          FlowyFormTextInput(
             hintText: "App name",
             onChanged: (text) {
               appName = text;

+ 1 - 1
app_flowy/lib/workspace/presentation/widgets/menu/menu.dart

@@ -130,7 +130,7 @@ class MenuItemBuilder {
   MenuItemBuilder withApps(Option<List<App>> someApps) {
     List<MenuItem> appWidgets = someApps.foldRight(
       [],
-      (apps, _) => apps.map((app) => AppWidget(app)).toList(),
+      (apps, _) => apps.map((app) => AppWidget(AppWidgetContext(app))).toList(),
     );
     items.addAll(appWidgets);
     return this;

+ 3 - 8
app_flowy/lib/workspace/presentation/widgets/menu/menu_new_app.dart

@@ -3,7 +3,7 @@ import 'package:app_flowy/workspace/presentation/widgets/menu/create_app_dialog.
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
 import 'package:flutter/material.dart';
-import 'package:styled_widget/styled_widget.dart';
+import 'package:flowy_infra_ui/style_widget/extension.dart';
 
 class NewAppButton extends StatelessWidget {
   final Function(String)? press;
@@ -11,12 +11,7 @@ class NewAppButton extends StatelessWidget {
   const NewAppButton({this.press, Key? key}) : super(key: key);
   @override
   Widget build(BuildContext context) {
-    return Container(
-      decoration: BoxDecoration(
-        border: Border(
-          top: BorderSide(width: 1, color: Colors.grey.shade300),
-        ),
-      ),
+    return SizedBox(
       height: HomeSizes.menuAddButtonHeight,
       child: Row(
         mainAxisAlignment: MainAxisAlignment.start,
@@ -35,7 +30,7 @@ class NewAppButton extends StatelessWidget {
           )
         ],
       ).padding(horizontal: Insets.l),
-    );
+    ).topBorder(color: Colors.grey.shade300);
   }
 
   Future<void> _showCreateAppDialog(BuildContext context) async {

+ 4 - 4
app_flowy/lib/workspace/presentation/widgets/menu/menu_user.dart

@@ -5,8 +5,8 @@ import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flowy_infra_ui/style_widget/styled_text.dart';
-import 'package:flowy_infra_ui/style_widget/styled_icon_button.dart';
+import 'package:flowy_infra_ui/style_widget/text.dart';
+import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 
 class MenuUser extends MenuItem {
   final UserDetail user;
@@ -46,12 +46,12 @@ class MenuUser extends MenuItem {
       name = context.read<MenuUserBloc>().state.user.email;
     }
     return Flexible(
-      child: StyledText(name, fontSize: 18),
+      child: FlowyText(name, fontSize: 18),
     );
   }
 
   Widget _renderDropButton(BuildContext context) {
-    return StyledIconButton(
+    return FlowyIconButton(
       width: 30,
       iconRatio: 0.8,
       icon: const Icon(Icons.arrow_drop_down),

+ 2 - 2
app_flowy/packages/flowy_infra_ui/lib/style_widget/styled_bar_title.dart → app_flowy/packages/flowy_infra_ui/lib/style_widget/bar_title.dart

@@ -1,9 +1,9 @@
 import 'package:flutter/material.dart';
 
-class StyleBarTitle extends StatelessWidget {
+class FlowyBarTitle extends StatelessWidget {
   final String title;
 
-  const StyleBarTitle({
+  const FlowyBarTitle({
     Key? key,
     required this.title,
   }) : super(key: key);

+ 2 - 2
app_flowy/packages/flowy_infra_ui/lib/style_widget/styled_close_button.dart → app_flowy/packages/flowy_infra_ui/lib/style_widget/close_button.dart

@@ -1,9 +1,9 @@
 import 'package:flutter/material.dart';
 
-class StyleCloseButton extends StatelessWidget {
+class FlowyCloseButton extends StatelessWidget {
   final VoidCallback? onPressed;
 
-  const StyleCloseButton({
+  const FlowyCloseButton({
     Key? key,
     this.onPressed,
   }) : super(key: key);

+ 2 - 2
app_flowy/packages/flowy_infra_ui/lib/style_widget/styled_container.dart → app_flowy/packages/flowy_infra_ui/lib/style_widget/container.dart

@@ -1,7 +1,7 @@
 import 'package:flowy_infra/time/duration.dart';
 import 'package:flutter/material.dart';
 
-class StyledContainer extends StatelessWidget {
+class FlowyContainer extends StatelessWidget {
   final Color color;
   final BorderRadiusGeometry? borderRadius;
   final List<BoxShadow>? shadows;
@@ -13,7 +13,7 @@ class StyledContainer extends StatelessWidget {
   final Duration? duration;
   final BoxBorder? border;
 
-  const StyledContainer(this.color,
+  const FlowyContainer(this.color,
       {Key? key,
       this.borderRadius,
       this.shadows,

+ 27 - 0
app_flowy/packages/flowy_infra_ui/lib/style_widget/extension.dart

@@ -0,0 +1,27 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+export 'package:styled_widget/styled_widget.dart';
+
+extension FlowyStyledWidget on Widget {
+  Widget bottomBorder({double width = 0.5, Color color = Colors.grey}) {
+    return Container(
+      decoration: BoxDecoration(
+        border: Border(
+          bottom: BorderSide(width: width, color: color),
+        ),
+      ),
+      child: this,
+    );
+  }
+
+  Widget topBorder({double width = 0.5, Color color = Colors.grey}) {
+    return Container(
+      decoration: BoxDecoration(
+        border: Border(
+          top: BorderSide(width: width, color: color),
+        ),
+      ),
+      child: this,
+    );
+  }
+}

+ 7 - 7
app_flowy/packages/flowy_infra_ui/lib/style_widget/styled_hover.dart → app_flowy/packages/flowy_infra_ui/lib/style_widget/hover.dart

@@ -4,21 +4,21 @@ import 'package:flowy_infra/time/duration.dart';
 
 typedef HoverBuilder = Widget Function(BuildContext context, bool onHover);
 
-class StyledHover extends StatefulWidget {
+class FlowyHover extends StatefulWidget {
   final HoverDisplayConfig config;
   final HoverBuilder builder;
 
-  const StyledHover({
+  const FlowyHover({
     Key? key,
     required this.builder,
     this.config = const HoverDisplayConfig(),
   }) : super(key: key);
 
   @override
-  State<StyledHover> createState() => _StyledHoverState();
+  State<FlowyHover> createState() => _FlowyHoverState();
 }
 
-class _StyledHoverState extends State<StyledHover> {
+class _FlowyHoverState extends State<FlowyHover> {
   bool _onHover = false;
 
   @override
@@ -32,7 +32,7 @@ class _StyledHoverState extends State<StyledHover> {
       cursor: SystemMouseCursors.click,
       onEnter: (p) => setOnHover(true),
       onExit: (p) => setOnHover(false),
-      child: HoverBackground(
+      child: FlowyHoverBackground(
           config: config, child: widget.builder(context, _onHover)),
     );
   }
@@ -61,12 +61,12 @@ class HoverDisplayConfig {
   }
 }
 
-class HoverBackground extends StatelessWidget {
+class FlowyHoverBackground extends StatelessWidget {
   final HoverDisplayConfig config;
 
   final Widget child;
 
-  const HoverBackground({
+  const FlowyHoverBackground({
     Key? key,
     required this.child,
     this.config = const HoverDisplayConfig(),

+ 5 - 5
app_flowy/packages/flowy_infra_ui/lib/style_widget/styled_icon_button.dart → app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart

@@ -1,13 +1,13 @@
 import 'package:flutter/material.dart';
 
-class StyledIconButton extends StatelessWidget {
+class FlowyIconButton extends StatelessWidget {
   final double width;
   final double? height;
   final double iconRatio;
   final Icon icon;
   final VoidCallback? onPressed;
 
-  const StyledIconButton({
+  const FlowyIconButton({
     Key? key,
     this.height,
     this.onPressed,
@@ -32,12 +32,12 @@ class StyledIconButton extends StatelessWidget {
   }
 }
 
-class StyledMore extends StatelessWidget {
+class FlowyMoreButton extends StatelessWidget {
   final double width;
   final double? height;
   final VoidCallback? onPressed;
 
-  const StyledMore({
+  const FlowyMoreButton({
     Key? key,
     this.height,
     this.onPressed,
@@ -46,7 +46,7 @@ class StyledMore extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return StyledIconButton(
+    return FlowyIconButton(
       width: width,
       height: height,
       icon: const Icon(Icons.more_vert),

+ 2 - 2
app_flowy/packages/flowy_infra_ui/lib/style_widget/styled_image_icon.dart → app_flowy/packages/flowy_infra_ui/lib/style_widget/image_icon.dart

@@ -1,12 +1,12 @@
 import 'package:flowy_infra/size.dart';
 import 'package:flutter/material.dart';
 
-class StyledImageIcon extends StatelessWidget {
+class FlowyImageIcon extends StatelessWidget {
   final AssetImage image;
   final Color? color;
   final double? size;
 
-  const StyledImageIcon(this.image, {Key? key, this.color, this.size})
+  const FlowyImageIcon(this.image, {Key? key, this.color, this.size})
       : super(key: key);
 
   @override

+ 4 - 3
app_flowy/packages/flowy_infra_ui/lib/style_widget/styled_navigation_list.dart → app_flowy/packages/flowy_infra_ui/lib/style_widget/navigation_list.dart

@@ -50,12 +50,13 @@ class StyledNavigationList extends StatelessWidget {
   List<NaviItem> _filter(List<NaviItem> items) {
     final length = items.length;
     if (length > 4) {
+      final first = items[0];
       final ellipsisItems = items.getRange(1, length - 2).toList();
+      final last = items.getRange(length - 2, length).toList();
       return [
-        items[0],
+        first,
         EllipsisNaviItem(items: ellipsisItems),
-        items[length - 2],
-        items[length - 1]
+        ...last,
       ];
     } else {
       return items;

+ 2 - 2
app_flowy/packages/flowy_infra_ui/lib/style_widget/styled_progress_indicator.dart → app_flowy/packages/flowy_infra_ui/lib/style_widget/progress_indicator.dart

@@ -13,8 +13,8 @@ List<Color> _kDefaultRainbowColors = const [
 ];
 
 // CircularProgressIndicator()
-class StyledProgressIndicator extends StatelessWidget {
-  const StyledProgressIndicator({Key? key}) : super(key: key);
+class FlowyProgressIndicator extends StatelessWidget {
+  const FlowyProgressIndicator({Key? key}) : super(key: key);
 
   @override
   Widget build(BuildContext context) {

+ 2 - 2
app_flowy/packages/flowy_infra_ui/lib/style_widget/styled_text.dart → app_flowy/packages/flowy_infra_ui/lib/style_widget/text.dart

@@ -1,10 +1,10 @@
 import 'package:flutter/widgets.dart';
 
-class StyledText extends StatelessWidget {
+class FlowyText extends StatelessWidget {
   final String title;
   final TextOverflow overflow;
   final double fontSize;
-  const StyledText(
+  const FlowyText(
     this.title, {
     Key? key,
     this.overflow = TextOverflow.ellipsis,

+ 6 - 6
app_flowy/packages/flowy_infra_ui/lib/style_widget/styled_text_button.dart → app_flowy/packages/flowy_infra_ui/lib/style_widget/text_button.dart

@@ -1,14 +1,14 @@
-import 'package:flowy_infra_ui/style_widget/styled_hover.dart';
-import 'package:flowy_infra_ui/style_widget/styled_text.dart';
+import 'package:flowy_infra_ui/style_widget/hover.dart';
+import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
 
-class StyledTextButton extends StatelessWidget {
+class FlowyTextButton extends StatelessWidget {
   final String text;
   final double fontSize;
   final VoidCallback? onPressed;
   final EdgeInsets padding;
-  const StyledTextButton(this.text,
+  const FlowyTextButton(this.text,
       {Key? key,
       this.onPressed,
       this.fontSize = 16,
@@ -19,7 +19,7 @@ class StyledTextButton extends StatelessWidget {
   Widget build(BuildContext context) {
     return InkWell(
       onTap: onPressed,
-      child: StyledHover(
+      child: FlowyHover(
         config: HoverDisplayConfig(
             borderRadius: BorderRadius.circular(8),
             hoverColor: Colors.grey.shade300),
@@ -33,7 +33,7 @@ class StyledTextButton extends StatelessWidget {
       padding: padding,
       child: Align(
         alignment: Alignment.centerLeft,
-        child: StyledText(text, fontSize: fontSize),
+        child: FlowyText(text, fontSize: fontSize),
       ),
     );
   }

+ 2 - 2
app_flowy/packages/flowy_infra_ui/lib/style_widget/styled_text_input.dart → app_flowy/packages/flowy_infra_ui/lib/style_widget/text_input.dart

@@ -9,7 +9,7 @@ import 'package:provider/provider.dart';
 // ignore: import_of_legacy_library_into_null_safe
 import 'package:textstyle_extensions/textstyle_extensions.dart';
 
-class StyledFormTextInput extends StatelessWidget {
+class FlowyFormTextInput extends StatelessWidget {
   static EdgeInsets kDefaultTextInputPadding =
       EdgeInsets.only(bottom: Insets.sm, top: 4);
 
@@ -27,7 +27,7 @@ class StyledFormTextInput extends StatelessWidget {
   final Function(bool)? onFocusChanged;
   final Function(FocusNode)? onFocusCreated;
 
-  const StyledFormTextInput(
+  const FlowyFormTextInput(
       {Key? key,
       this.label,
       this.autoFocus,

+ 2 - 2
app_flowy/packages/flowy_infra_ui/lib/widget/buttons/secondary_button.dart

@@ -1,4 +1,4 @@
-import 'package:flowy_infra_ui/style_widget/styled_image_icon.dart';
+import 'package:flowy_infra_ui/style_widget/image_icon.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 // ignore: import_of_legacy_library_into_null_safe
@@ -42,7 +42,7 @@ class SecondaryIconButton extends StatelessWidget {
       minHeight: 36,
       minWidth: 36,
       contentPadding: Insets.sm,
-      child: StyledImageIcon(icon, size: 20, color: color ?? theme.grey),
+      child: FlowyImageIcon(icon, size: 20, color: color ?? theme.grey),
     );
   }
 }

+ 15 - 0
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_create.pb.dart

@@ -7,6 +7,7 @@
 
 import 'dart:core' as $core;
 
+import 'package:fixnum/fixnum.dart' as $fixnum;
 import 'package:protobuf/protobuf.dart' as $pb;
 
 import 'view_create.pb.dart' as $0;
@@ -156,6 +157,7 @@ class App extends $pb.GeneratedMessage {
     ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
     ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
     ..aOM<$0.RepeatedView>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'views', subBuilder: $0.RepeatedView.create)
+    ..aInt64(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'version')
     ..hasRequiredFields = false
   ;
 
@@ -166,6 +168,7 @@ class App extends $pb.GeneratedMessage {
     $core.String? name,
     $core.String? desc,
     $0.RepeatedView? views,
+    $fixnum.Int64? version,
   }) {
     final _result = create();
     if (id != null) {
@@ -183,6 +186,9 @@ class App extends $pb.GeneratedMessage {
     if (views != null) {
       _result.views = views;
     }
+    if (version != null) {
+      _result.version = version;
+    }
     return _result;
   }
   factory App.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
@@ -252,6 +258,15 @@ class App extends $pb.GeneratedMessage {
   void clearViews() => clearField(5);
   @$pb.TagNumber(5)
   $0.RepeatedView ensureViews() => $_ensure(4);
+
+  @$pb.TagNumber(6)
+  $fixnum.Int64 get version => $_getI64(5);
+  @$pb.TagNumber(6)
+  set version($fixnum.Int64 v) { $_setInt64(5, v); }
+  @$pb.TagNumber(6)
+  $core.bool hasVersion() => $_has(5);
+  @$pb.TagNumber(6)
+  void clearVersion() => clearField(6);
 }
 
 class RepeatedApp extends $pb.GeneratedMessage {

+ 2 - 1
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_create.pbjson.dart

@@ -40,11 +40,12 @@ const App$json = const {
     const {'1': 'name', '3': 3, '4': 1, '5': 9, '10': 'name'},
     const {'1': 'desc', '3': 4, '4': 1, '5': 9, '10': 'desc'},
     const {'1': 'views', '3': 5, '4': 1, '5': 11, '6': '.RepeatedView', '10': 'views'},
+    const {'1': 'version', '3': 6, '4': 1, '5': 3, '10': 'version'},
   ],
 };
 
 /// Descriptor for `App`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List appDescriptor = $convert.base64Decode('CgNBcHASDgoCaWQYASABKAlSAmlkEiEKDHdvcmtzcGFjZV9pZBgCIAEoCVILd29ya3NwYWNlSWQSEgoEbmFtZRgDIAEoCVIEbmFtZRISCgRkZXNjGAQgASgJUgRkZXNjEiMKBXZpZXdzGAUgASgLMg0uUmVwZWF0ZWRWaWV3UgV2aWV3cw==');
+final $typed_data.Uint8List appDescriptor = $convert.base64Decode('CgNBcHASDgoCaWQYASABKAlSAmlkEiEKDHdvcmtzcGFjZV9pZBgCIAEoCVILd29ya3NwYWNlSWQSEgoEbmFtZRgDIAEoCVIEbmFtZRISCgRkZXNjGAQgASgJUgRkZXNjEiMKBXZpZXdzGAUgASgLMg0uUmVwZWF0ZWRWaWV3UgV2aWV3cxIYCgd2ZXJzaW9uGAYgASgDUgd2ZXJzaW9u');
 @$core.Deprecated('Use repeatedAppDescriptor instead')
 const RepeatedApp$json = const {
   '1': 'RepeatedApp',

+ 15 - 0
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pb.dart

@@ -7,6 +7,7 @@
 
 import 'dart:core' as $core;
 
+import 'package:fixnum/fixnum.dart' as $fixnum;
 import 'package:protobuf/protobuf.dart' as $pb;
 
 import 'view_create.pbenum.dart';
@@ -136,6 +137,7 @@ class View extends $pb.GeneratedMessage {
     ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
     ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
     ..e<ViewType>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewType', $pb.PbFieldType.OE, defaultOrMaker: ViewType.Blank, valueOf: ViewType.valueOf, enumValues: ViewType.values)
+    ..aInt64(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'version')
     ..hasRequiredFields = false
   ;
 
@@ -146,6 +148,7 @@ class View extends $pb.GeneratedMessage {
     $core.String? name,
     $core.String? desc,
     ViewType? viewType,
+    $fixnum.Int64? version,
   }) {
     final _result = create();
     if (id != null) {
@@ -163,6 +166,9 @@ class View extends $pb.GeneratedMessage {
     if (viewType != null) {
       _result.viewType = viewType;
     }
+    if (version != null) {
+      _result.version = version;
+    }
     return _result;
   }
   factory View.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
@@ -230,6 +236,15 @@ class View extends $pb.GeneratedMessage {
   $core.bool hasViewType() => $_has(4);
   @$pb.TagNumber(5)
   void clearViewType() => clearField(5);
+
+  @$pb.TagNumber(6)
+  $fixnum.Int64 get version => $_getI64(5);
+  @$pb.TagNumber(6)
+  set version($fixnum.Int64 v) { $_setInt64(5, v); }
+  @$pb.TagNumber(6)
+  $core.bool hasVersion() => $_has(5);
+  @$pb.TagNumber(6)
+  void clearVersion() => clearField(6);
 }
 
 class RepeatedView extends $pb.GeneratedMessage {

+ 2 - 1
app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pbjson.dart

@@ -45,11 +45,12 @@ const View$json = const {
     const {'1': 'name', '3': 3, '4': 1, '5': 9, '10': 'name'},
     const {'1': 'desc', '3': 4, '4': 1, '5': 9, '10': 'desc'},
     const {'1': 'view_type', '3': 5, '4': 1, '5': 14, '6': '.ViewType', '10': 'viewType'},
+    const {'1': 'version', '3': 6, '4': 1, '5': 3, '10': 'version'},
   ],
 };
 
 /// Descriptor for `View`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List viewDescriptor = $convert.base64Decode('CgRWaWV3Eg4KAmlkGAEgASgJUgJpZBIgCgxiZWxvbmdfdG9faWQYAiABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgDIAEoCVIEbmFtZRISCgRkZXNjGAQgASgJUgRkZXNjEiYKCXZpZXdfdHlwZRgFIAEoDjIJLlZpZXdUeXBlUgh2aWV3VHlwZQ==');
+final $typed_data.Uint8List viewDescriptor = $convert.base64Decode('CgRWaWV3Eg4KAmlkGAEgASgJUgJpZBIgCgxiZWxvbmdfdG9faWQYAiABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgDIAEoCVIEbmFtZRISCgRkZXNjGAQgASgJUgRkZXNjEiYKCXZpZXdfdHlwZRgFIAEoDjIJLlZpZXdUeXBlUgh2aWV3VHlwZRIYCgd2ZXJzaW9uGAYgASgDUgd2ZXJzaW9u');
 @$core.Deprecated('Use repeatedViewDescriptor instead')
 const RepeatedView$json = const {
   '1': 'RepeatedView',

+ 3 - 0
rust-lib/flowy-workspace/src/entities/app/app_create.rs

@@ -82,6 +82,9 @@ pub struct App {
 
     #[pb(index = 5)]
     pub views: RepeatedView,
+
+    #[pb(index = 6)]
+    pub version: i64,
 }
 
 #[derive(PartialEq, Debug, Default, ProtoBuf)]

+ 3 - 0
rust-lib/flowy-workspace/src/entities/view/view_create.rs

@@ -95,6 +95,9 @@ pub struct View {
 
     #[pb(index = 5)]
     pub view_type: ViewType,
+
+    #[pb(index = 6)]
+    pub version: i64,
 }
 
 #[derive(PartialEq, Debug, Default, ProtoBuf)]

+ 78 - 40
rust-lib/flowy-workspace/src/protobuf/model/app_create.rs

@@ -490,6 +490,7 @@ pub struct App {
     pub name: ::std::string::String,
     pub desc: ::std::string::String,
     pub views: ::protobuf::SingularPtrField<super::view_create::RepeatedView>,
+    pub version: i64,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
@@ -642,6 +643,21 @@ impl App {
     pub fn take_views(&mut self) -> super::view_create::RepeatedView {
         self.views.take().unwrap_or_else(|| super::view_create::RepeatedView::new())
     }
+
+    // int64 version = 6;
+
+
+    pub fn get_version(&self) -> i64 {
+        self.version
+    }
+    pub fn clear_version(&mut self) {
+        self.version = 0;
+    }
+
+    // Param is passed by value, moved
+    pub fn set_version(&mut self, v: i64) {
+        self.version = v;
+    }
 }
 
 impl ::protobuf::Message for App {
@@ -673,6 +689,13 @@ impl ::protobuf::Message for App {
                 5 => {
                     ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.views)?;
                 },
+                6 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeVarint {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    let tmp = is.read_int64()?;
+                    self.version = tmp;
+                },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
                 },
@@ -701,6 +724,9 @@ impl ::protobuf::Message for App {
             let len = v.compute_size();
             my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
         }
+        if self.version != 0 {
+            my_size += ::protobuf::rt::value_size(6, self.version, ::protobuf::wire_format::WireTypeVarint);
+        }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
         my_size
@@ -724,6 +750,9 @@ impl ::protobuf::Message for App {
             os.write_raw_varint32(v.get_cached_size())?;
             v.write_to_with_cached_sizes(os)?;
         }
+        if self.version != 0 {
+            os.write_int64(6, self.version)?;
+        }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
     }
@@ -787,6 +816,11 @@ impl ::protobuf::Message for App {
                 |m: &App| { &m.views },
                 |m: &mut App| { &mut m.views },
             ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt64>(
+                "version",
+                |m: &App| { &m.version },
+                |m: &mut App| { &mut m.version },
+            ));
             ::protobuf::reflect::MessageDescriptor::new_pb_name::<App>(
                 "App",
                 fields,
@@ -808,6 +842,7 @@ impl ::protobuf::Clear for App {
         self.name.clear();
         self.desc.clear();
         self.views.clear();
+        self.version = 0;
         self.unknown_fields.clear();
     }
 }
@@ -996,49 +1031,52 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     \x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\
     \x01(\tR\x04desc\x12,\n\x0bcolor_style\x18\x04\x20\x01(\x0b2\x0b.ColorSt\
     yleR\ncolorStyle\"-\n\nColorStyle\x12\x1f\n\x0btheme_color\x18\x01\x20\
-    \x01(\tR\nthemeColor\"\x85\x01\n\x03App\x12\x0e\n\x02id\x18\x01\x20\x01(\
+    \x01(\tR\nthemeColor\"\x9f\x01\n\x03App\x12\x0e\n\x02id\x18\x01\x20\x01(\
     \tR\x02id\x12!\n\x0cworkspace_id\x18\x02\x20\x01(\tR\x0bworkspaceId\x12\
     \x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x04\x20\
     \x01(\tR\x04desc\x12#\n\x05views\x18\x05\x20\x01(\x0b2\r.RepeatedViewR\
-    \x05views\")\n\x0bRepeatedApp\x12\x1a\n\x05items\x18\x01\x20\x03(\x0b2\
-    \x04.AppR\x05itemsJ\xe8\x05\n\x06\x12\x04\0\0\x15\x01\n\x08\n\x01\x0c\
-    \x12\x03\0\0\x12\n\t\n\x02\x03\0\x12\x03\x01\0\x1b\n\n\n\x02\x04\0\x12\
-    \x04\x03\0\x08\x01\n\n\n\x03\x04\0\x01\x12\x03\x03\x08\x18\n\x0b\n\x04\
-    \x04\0\x02\0\x12\x03\x04\x04\x1c\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x04\
-    \x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x04\x0b\x17\n\x0c\n\x05\x04\0\
-    \x02\0\x03\x12\x03\x04\x1a\x1b\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x05\x04\
-    \x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\0\
-    \x02\x01\x01\x12\x03\x05\x0b\x0f\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\
-    \x05\x12\x13\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x06\x04\x14\n\x0c\n\x05\
-    \x04\0\x02\x02\x05\x12\x03\x06\x04\n\n\x0c\n\x05\x04\0\x02\x02\x01\x12\
-    \x03\x06\x0b\x0f\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x06\x12\x13\n\x0b\
-    \n\x04\x04\0\x02\x03\x12\x03\x07\x04\x1f\n\x0c\n\x05\x04\0\x02\x03\x06\
-    \x12\x03\x07\x04\x0e\n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x07\x0f\x1a\n\
-    \x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x07\x1d\x1e\n\n\n\x02\x04\x01\x12\
-    \x04\t\0\x0b\x01\n\n\n\x03\x04\x01\x01\x12\x03\t\x08\x12\n\x0b\n\x04\x04\
-    \x01\x02\0\x12\x03\n\x04\x1b\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\n\x04\
-    \n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\n\x0b\x16\n\x0c\n\x05\x04\x01\
-    \x02\0\x03\x12\x03\n\x19\x1a\n\n\n\x02\x04\x02\x12\x04\x0c\0\x12\x01\n\n\
-    \n\x03\x04\x02\x01\x12\x03\x0c\x08\x0b\n\x0b\n\x04\x04\x02\x02\0\x12\x03\
-    \r\x04\x12\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\r\x04\n\n\x0c\n\x05\x04\
-    \x02\x02\0\x01\x12\x03\r\x0b\r\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\r\
-    \x10\x11\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\x0e\x04\x1c\n\x0c\n\x05\x04\
-    \x02\x02\x01\x05\x12\x03\x0e\x04\n\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\
-    \x03\x0e\x0b\x17\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03\x0e\x1a\x1b\n\
-    \x0b\n\x04\x04\x02\x02\x02\x12\x03\x0f\x04\x14\n\x0c\n\x05\x04\x02\x02\
-    \x02\x05\x12\x03\x0f\x04\n\n\x0c\n\x05\x04\x02\x02\x02\x01\x12\x03\x0f\
-    \x0b\x0f\n\x0c\n\x05\x04\x02\x02\x02\x03\x12\x03\x0f\x12\x13\n\x0b\n\x04\
-    \x04\x02\x02\x03\x12\x03\x10\x04\x14\n\x0c\n\x05\x04\x02\x02\x03\x05\x12\
-    \x03\x10\x04\n\n\x0c\n\x05\x04\x02\x02\x03\x01\x12\x03\x10\x0b\x0f\n\x0c\
-    \n\x05\x04\x02\x02\x03\x03\x12\x03\x10\x12\x13\n\x0b\n\x04\x04\x02\x02\
-    \x04\x12\x03\x11\x04\x1b\n\x0c\n\x05\x04\x02\x02\x04\x06\x12\x03\x11\x04\
-    \x10\n\x0c\n\x05\x04\x02\x02\x04\x01\x12\x03\x11\x11\x16\n\x0c\n\x05\x04\
-    \x02\x02\x04\x03\x12\x03\x11\x19\x1a\n\n\n\x02\x04\x03\x12\x04\x13\0\x15\
-    \x01\n\n\n\x03\x04\x03\x01\x12\x03\x13\x08\x13\n\x0b\n\x04\x04\x03\x02\0\
-    \x12\x03\x14\x04\x1b\n\x0c\n\x05\x04\x03\x02\0\x04\x12\x03\x14\x04\x0c\n\
-    \x0c\n\x05\x04\x03\x02\0\x06\x12\x03\x14\r\x10\n\x0c\n\x05\x04\x03\x02\0\
-    \x01\x12\x03\x14\x11\x16\n\x0c\n\x05\x04\x03\x02\0\x03\x12\x03\x14\x19\
-    \x1ab\x06proto3\
+    \x05views\x12\x18\n\x07version\x18\x06\x20\x01(\x03R\x07version\")\n\x0b\
+    RepeatedApp\x12\x1a\n\x05items\x18\x01\x20\x03(\x0b2\x04.AppR\x05itemsJ\
+    \x9f\x06\n\x06\x12\x04\0\0\x16\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\t\n\
+    \x02\x03\0\x12\x03\x01\0\x1b\n\n\n\x02\x04\0\x12\x04\x03\0\x08\x01\n\n\n\
+    \x03\x04\0\x01\x12\x03\x03\x08\x18\n\x0b\n\x04\x04\0\x02\0\x12\x03\x04\
+    \x04\x1c\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\
+    \x02\0\x01\x12\x03\x04\x0b\x17\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x04\
+    \x1a\x1b\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x05\x04\x14\n\x0c\n\x05\x04\0\
+    \x02\x01\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x05\
+    \x0b\x0f\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x05\x12\x13\n\x0b\n\x04\
+    \x04\0\x02\x02\x12\x03\x06\x04\x14\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\
+    \x06\x04\n\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x06\x0b\x0f\n\x0c\n\x05\
+    \x04\0\x02\x02\x03\x12\x03\x06\x12\x13\n\x0b\n\x04\x04\0\x02\x03\x12\x03\
+    \x07\x04\x1f\n\x0c\n\x05\x04\0\x02\x03\x06\x12\x03\x07\x04\x0e\n\x0c\n\
+    \x05\x04\0\x02\x03\x01\x12\x03\x07\x0f\x1a\n\x0c\n\x05\x04\0\x02\x03\x03\
+    \x12\x03\x07\x1d\x1e\n\n\n\x02\x04\x01\x12\x04\t\0\x0b\x01\n\n\n\x03\x04\
+    \x01\x01\x12\x03\t\x08\x12\n\x0b\n\x04\x04\x01\x02\0\x12\x03\n\x04\x1b\n\
+    \x0c\n\x05\x04\x01\x02\0\x05\x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\x02\0\
+    \x01\x12\x03\n\x0b\x16\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\n\x19\x1a\n\
+    \n\n\x02\x04\x02\x12\x04\x0c\0\x13\x01\n\n\n\x03\x04\x02\x01\x12\x03\x0c\
+    \x08\x0b\n\x0b\n\x04\x04\x02\x02\0\x12\x03\r\x04\x12\n\x0c\n\x05\x04\x02\
+    \x02\0\x05\x12\x03\r\x04\n\n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03\r\x0b\r\
+    \n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\r\x10\x11\n\x0b\n\x04\x04\x02\x02\
+    \x01\x12\x03\x0e\x04\x1c\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\x03\x0e\x04\
+    \n\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\x0e\x0b\x17\n\x0c\n\x05\x04\
+    \x02\x02\x01\x03\x12\x03\x0e\x1a\x1b\n\x0b\n\x04\x04\x02\x02\x02\x12\x03\
+    \x0f\x04\x14\n\x0c\n\x05\x04\x02\x02\x02\x05\x12\x03\x0f\x04\n\n\x0c\n\
+    \x05\x04\x02\x02\x02\x01\x12\x03\x0f\x0b\x0f\n\x0c\n\x05\x04\x02\x02\x02\
+    \x03\x12\x03\x0f\x12\x13\n\x0b\n\x04\x04\x02\x02\x03\x12\x03\x10\x04\x14\
+    \n\x0c\n\x05\x04\x02\x02\x03\x05\x12\x03\x10\x04\n\n\x0c\n\x05\x04\x02\
+    \x02\x03\x01\x12\x03\x10\x0b\x0f\n\x0c\n\x05\x04\x02\x02\x03\x03\x12\x03\
+    \x10\x12\x13\n\x0b\n\x04\x04\x02\x02\x04\x12\x03\x11\x04\x1b\n\x0c\n\x05\
+    \x04\x02\x02\x04\x06\x12\x03\x11\x04\x10\n\x0c\n\x05\x04\x02\x02\x04\x01\
+    \x12\x03\x11\x11\x16\n\x0c\n\x05\x04\x02\x02\x04\x03\x12\x03\x11\x19\x1a\
+    \n\x0b\n\x04\x04\x02\x02\x05\x12\x03\x12\x04\x16\n\x0c\n\x05\x04\x02\x02\
+    \x05\x05\x12\x03\x12\x04\t\n\x0c\n\x05\x04\x02\x02\x05\x01\x12\x03\x12\n\
+    \x11\n\x0c\n\x05\x04\x02\x02\x05\x03\x12\x03\x12\x14\x15\n\n\n\x02\x04\
+    \x03\x12\x04\x14\0\x16\x01\n\n\n\x03\x04\x03\x01\x12\x03\x14\x08\x13\n\
+    \x0b\n\x04\x04\x03\x02\0\x12\x03\x15\x04\x1b\n\x0c\n\x05\x04\x03\x02\0\
+    \x04\x12\x03\x15\x04\x0c\n\x0c\n\x05\x04\x03\x02\0\x06\x12\x03\x15\r\x10\
+    \n\x0c\n\x05\x04\x03\x02\0\x01\x12\x03\x15\x11\x16\n\x0c\n\x05\x04\x03\
+    \x02\0\x03\x12\x03\x15\x19\x1ab\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 84 - 46
rust-lib/flowy-workspace/src/protobuf/model/view_create.rs

@@ -387,6 +387,7 @@ pub struct View {
     pub name: ::std::string::String,
     pub desc: ::std::string::String,
     pub view_type: ViewType,
+    pub version: i64,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
@@ -521,6 +522,21 @@ impl View {
     pub fn set_view_type(&mut self, v: ViewType) {
         self.view_type = v;
     }
+
+    // int64 version = 6;
+
+
+    pub fn get_version(&self) -> i64 {
+        self.version
+    }
+    pub fn clear_version(&mut self) {
+        self.version = 0;
+    }
+
+    // Param is passed by value, moved
+    pub fn set_version(&mut self, v: i64) {
+        self.version = v;
+    }
 }
 
 impl ::protobuf::Message for View {
@@ -547,6 +563,13 @@ impl ::protobuf::Message for View {
                 5 => {
                     ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.view_type, 5, &mut self.unknown_fields)?
                 },
+                6 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeVarint {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    let tmp = is.read_int64()?;
+                    self.version = tmp;
+                },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
                 },
@@ -574,6 +597,9 @@ impl ::protobuf::Message for View {
         if self.view_type != ViewType::Blank {
             my_size += ::protobuf::rt::enum_size(5, self.view_type);
         }
+        if self.version != 0 {
+            my_size += ::protobuf::rt::value_size(6, self.version, ::protobuf::wire_format::WireTypeVarint);
+        }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
         my_size
@@ -595,6 +621,9 @@ impl ::protobuf::Message for View {
         if self.view_type != ViewType::Blank {
             os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.view_type))?;
         }
+        if self.version != 0 {
+            os.write_int64(6, self.version)?;
+        }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
     }
@@ -658,6 +687,11 @@ impl ::protobuf::Message for View {
                 |m: &View| { &m.view_type },
                 |m: &mut View| { &mut m.view_type },
             ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt64>(
+                "version",
+                |m: &View| { &m.version },
+                |m: &mut View| { &mut m.version },
+            ));
             ::protobuf::reflect::MessageDescriptor::new_pb_name::<View>(
                 "View",
                 fields,
@@ -679,6 +713,7 @@ impl ::protobuf::Clear for View {
         self.name.clear();
         self.desc.clear();
         self.view_type = ViewType::Blank;
+        self.version = 0;
         self.unknown_fields.clear();
     }
 }
@@ -916,55 +951,58 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     long_to_id\x18\x01\x20\x01(\tR\nbelongToId\x12\x12\n\x04name\x18\x02\x20\
     \x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12\x1e\n\
     \tthumbnail\x18\x04\x20\x01(\tH\0R\tthumbnail\x12&\n\tview_type\x18\x05\
-    \x20\x01(\x0e2\t.ViewTypeR\x08viewTypeB\x12\n\x10one_of_thumbnail\"\x88\
+    \x20\x01(\x0e2\t.ViewTypeR\x08viewTypeB\x12\n\x10one_of_thumbnail\"\xa2\
     \x01\n\x04View\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x20\n\x0cbe\
     long_to_id\x18\x02\x20\x01(\tR\nbelongToId\x12\x12\n\x04name\x18\x03\x20\
     \x01(\tR\x04name\x12\x12\n\x04desc\x18\x04\x20\x01(\tR\x04desc\x12&\n\tv\
-    iew_type\x18\x05\x20\x01(\x0e2\t.ViewTypeR\x08viewType\"+\n\x0cRepeatedV\
-    iew\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.ViewR\x05items*\x1e\n\
-    \x08ViewType\x12\t\n\x05Blank\x10\0\x12\x07\n\x03Doc\x10\x01J\xca\x06\n\
-    \x06\x12\x04\0\0\x16\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\
-    \x12\x04\x02\0\x08\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x19\n\x0b\n\
-    \x04\x04\0\x02\0\x12\x03\x03\x04\x1c\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\
-    \x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x17\n\x0c\n\x05\
-    \x04\0\x02\0\x03\x12\x03\x03\x1a\x1b\n\x0b\n\x04\x04\0\x02\x01\x12\x03\
-    \x04\x04\x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\
-    \x04\0\x02\x01\x01\x12\x03\x04\x0b\x0f\n\x0c\n\x05\x04\0\x02\x01\x03\x12\
-    \x03\x04\x12\x13\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x14\n\x0c\n\
-    \x05\x04\0\x02\x02\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\0\x02\x02\x01\
-    \x12\x03\x05\x0b\x0f\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x12\x13\n\
-    \x0b\n\x04\x04\0\x08\0\x12\x03\x06\x044\n\x0c\n\x05\x04\0\x08\0\x01\x12\
-    \x03\x06\n\x1a\n\x0b\n\x04\x04\0\x02\x03\x12\x03\x06\x1d2\n\x0c\n\x05\
-    \x04\0\x02\x03\x05\x12\x03\x06\x1d#\n\x0c\n\x05\x04\0\x02\x03\x01\x12\
-    \x03\x06$-\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x0601\n\x0b\n\x04\x04\0\
-    \x02\x04\x12\x03\x07\x04\x1b\n\x0c\n\x05\x04\0\x02\x04\x06\x12\x03\x07\
-    \x04\x0c\n\x0c\n\x05\x04\0\x02\x04\x01\x12\x03\x07\r\x16\n\x0c\n\x05\x04\
-    \0\x02\x04\x03\x12\x03\x07\x19\x1a\n\n\n\x02\x04\x01\x12\x04\t\0\x0f\x01\
-    \n\n\n\x03\x04\x01\x01\x12\x03\t\x08\x0c\n\x0b\n\x04\x04\x01\x02\0\x12\
-    \x03\n\x04\x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\n\x04\n\n\x0c\n\x05\
-    \x04\x01\x02\0\x01\x12\x03\n\x0b\r\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\
-    \n\x10\x11\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\x0b\x04\x1c\n\x0c\n\x05\
-    \x04\x01\x02\x01\x05\x12\x03\x0b\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\
-    \x12\x03\x0b\x0b\x17\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\x0b\x1a\x1b\
-    \n\x0b\n\x04\x04\x01\x02\x02\x12\x03\x0c\x04\x14\n\x0c\n\x05\x04\x01\x02\
-    \x02\x05\x12\x03\x0c\x04\n\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\x0c\
-    \x0b\x0f\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\x0c\x12\x13\n\x0b\n\x04\
-    \x04\x01\x02\x03\x12\x03\r\x04\x14\n\x0c\n\x05\x04\x01\x02\x03\x05\x12\
-    \x03\r\x04\n\n\x0c\n\x05\x04\x01\x02\x03\x01\x12\x03\r\x0b\x0f\n\x0c\n\
-    \x05\x04\x01\x02\x03\x03\x12\x03\r\x12\x13\n\x0b\n\x04\x04\x01\x02\x04\
-    \x12\x03\x0e\x04\x1b\n\x0c\n\x05\x04\x01\x02\x04\x06\x12\x03\x0e\x04\x0c\
-    \n\x0c\n\x05\x04\x01\x02\x04\x01\x12\x03\x0e\r\x16\n\x0c\n\x05\x04\x01\
-    \x02\x04\x03\x12\x03\x0e\x19\x1a\n\n\n\x02\x04\x02\x12\x04\x10\0\x12\x01\
-    \n\n\n\x03\x04\x02\x01\x12\x03\x10\x08\x14\n\x0b\n\x04\x04\x02\x02\0\x12\
-    \x03\x11\x04\x1c\n\x0c\n\x05\x04\x02\x02\0\x04\x12\x03\x11\x04\x0c\n\x0c\
-    \n\x05\x04\x02\x02\0\x06\x12\x03\x11\r\x11\n\x0c\n\x05\x04\x02\x02\0\x01\
-    \x12\x03\x11\x12\x17\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x11\x1a\x1b\n\
-    \n\n\x02\x05\0\x12\x04\x13\0\x16\x01\n\n\n\x03\x05\0\x01\x12\x03\x13\x05\
-    \r\n\x0b\n\x04\x05\0\x02\0\x12\x03\x14\x04\x0e\n\x0c\n\x05\x05\0\x02\0\
-    \x01\x12\x03\x14\x04\t\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x14\x0c\r\n\
-    \x0b\n\x04\x05\0\x02\x01\x12\x03\x15\x04\x0c\n\x0c\n\x05\x05\0\x02\x01\
-    \x01\x12\x03\x15\x04\x07\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x15\n\x0b\
-    b\x06proto3\
+    iew_type\x18\x05\x20\x01(\x0e2\t.ViewTypeR\x08viewType\x12\x18\n\x07vers\
+    ion\x18\x06\x20\x01(\x03R\x07version\"+\n\x0cRepeatedView\x12\x1b\n\x05i\
+    tems\x18\x01\x20\x03(\x0b2\x05.ViewR\x05items*\x1e\n\x08ViewType\x12\t\n\
+    \x05Blank\x10\0\x12\x07\n\x03Doc\x10\x01J\x81\x07\n\x06\x12\x04\0\0\x17\
+    \x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x08\
+    \x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x19\n\x0b\n\x04\x04\0\x02\0\x12\
+    \x03\x03\x04\x1c\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\
+    \x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x17\n\x0c\n\x05\x04\0\x02\0\x03\x12\
+    \x03\x03\x1a\x1b\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x14\n\x0c\n\
+    \x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\
+    \x12\x03\x04\x0b\x0f\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x12\x13\n\
+    \x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x14\n\x0c\n\x05\x04\0\x02\x02\
+    \x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\x0b\x0f\
+    \n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x12\x13\n\x0b\n\x04\x04\0\x08\
+    \0\x12\x03\x06\x044\n\x0c\n\x05\x04\0\x08\0\x01\x12\x03\x06\n\x1a\n\x0b\
+    \n\x04\x04\0\x02\x03\x12\x03\x06\x1d2\n\x0c\n\x05\x04\0\x02\x03\x05\x12\
+    \x03\x06\x1d#\n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x06$-\n\x0c\n\x05\
+    \x04\0\x02\x03\x03\x12\x03\x0601\n\x0b\n\x04\x04\0\x02\x04\x12\x03\x07\
+    \x04\x1b\n\x0c\n\x05\x04\0\x02\x04\x06\x12\x03\x07\x04\x0c\n\x0c\n\x05\
+    \x04\0\x02\x04\x01\x12\x03\x07\r\x16\n\x0c\n\x05\x04\0\x02\x04\x03\x12\
+    \x03\x07\x19\x1a\n\n\n\x02\x04\x01\x12\x04\t\0\x10\x01\n\n\n\x03\x04\x01\
+    \x01\x12\x03\t\x08\x0c\n\x0b\n\x04\x04\x01\x02\0\x12\x03\n\x04\x12\n\x0c\
+    \n\x05\x04\x01\x02\0\x05\x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\
+    \x12\x03\n\x0b\r\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\n\x10\x11\n\x0b\n\
+    \x04\x04\x01\x02\x01\x12\x03\x0b\x04\x1c\n\x0c\n\x05\x04\x01\x02\x01\x05\
+    \x12\x03\x0b\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x0b\x0b\x17\n\
+    \x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\x0b\x1a\x1b\n\x0b\n\x04\x04\x01\
+    \x02\x02\x12\x03\x0c\x04\x14\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\x0c\
+    \x04\n\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\x0c\x0b\x0f\n\x0c\n\x05\
+    \x04\x01\x02\x02\x03\x12\x03\x0c\x12\x13\n\x0b\n\x04\x04\x01\x02\x03\x12\
+    \x03\r\x04\x14\n\x0c\n\x05\x04\x01\x02\x03\x05\x12\x03\r\x04\n\n\x0c\n\
+    \x05\x04\x01\x02\x03\x01\x12\x03\r\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x03\
+    \x03\x12\x03\r\x12\x13\n\x0b\n\x04\x04\x01\x02\x04\x12\x03\x0e\x04\x1b\n\
+    \x0c\n\x05\x04\x01\x02\x04\x06\x12\x03\x0e\x04\x0c\n\x0c\n\x05\x04\x01\
+    \x02\x04\x01\x12\x03\x0e\r\x16\n\x0c\n\x05\x04\x01\x02\x04\x03\x12\x03\
+    \x0e\x19\x1a\n\x0b\n\x04\x04\x01\x02\x05\x12\x03\x0f\x04\x16\n\x0c\n\x05\
+    \x04\x01\x02\x05\x05\x12\x03\x0f\x04\t\n\x0c\n\x05\x04\x01\x02\x05\x01\
+    \x12\x03\x0f\n\x11\n\x0c\n\x05\x04\x01\x02\x05\x03\x12\x03\x0f\x14\x15\n\
+    \n\n\x02\x04\x02\x12\x04\x11\0\x13\x01\n\n\n\x03\x04\x02\x01\x12\x03\x11\
+    \x08\x14\n\x0b\n\x04\x04\x02\x02\0\x12\x03\x12\x04\x1c\n\x0c\n\x05\x04\
+    \x02\x02\0\x04\x12\x03\x12\x04\x0c\n\x0c\n\x05\x04\x02\x02\0\x06\x12\x03\
+    \x12\r\x11\n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03\x12\x12\x17\n\x0c\n\x05\
+    \x04\x02\x02\0\x03\x12\x03\x12\x1a\x1b\n\n\n\x02\x05\0\x12\x04\x14\0\x17\
+    \x01\n\n\n\x03\x05\0\x01\x12\x03\x14\x05\r\n\x0b\n\x04\x05\0\x02\0\x12\
+    \x03\x15\x04\x0e\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x15\x04\t\n\x0c\n\
+    \x05\x05\0\x02\0\x02\x12\x03\x15\x0c\r\n\x0b\n\x04\x05\0\x02\x01\x12\x03\
+    \x16\x04\x0c\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x16\x04\x07\n\x0c\n\
+    \x05\x05\0\x02\x01\x02\x12\x03\x16\n\x0bb\x06proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 1 - 0
rust-lib/flowy-workspace/src/protobuf/proto/app_create.proto

@@ -16,6 +16,7 @@ message App {
     string name = 3;
     string desc = 4;
     RepeatedView views = 5;
+    int64 version = 6;
 }
 message RepeatedApp {
     repeated App items = 1;

+ 1 - 0
rust-lib/flowy-workspace/src/protobuf/proto/view_create.proto

@@ -13,6 +13,7 @@ message View {
     string name = 3;
     string desc = 4;
     ViewType view_type = 5;
+    int64 version = 6;
 }
 message RepeatedView {
     repeated View items = 1;

+ 1 - 0
rust-lib/flowy-workspace/src/sql_tables/app/app_table.rs

@@ -105,6 +105,7 @@ impl std::convert::Into<App> for AppTable {
             name: self.name,
             desc: self.desc,
             views: RepeatedView::default(),
+            version: self.version,
         }
     }
 }

+ 1 - 0
rust-lib/flowy-workspace/src/sql_tables/view/view_table.rs

@@ -52,6 +52,7 @@ impl std::convert::Into<View> for ViewTable {
             name: self.name,
             desc: self.desc,
             view_type,
+            version: self.version,
         }
     }
 }