Explorar o código

refactor: show plugin

appflowy %!s(int64=3) %!d(string=hai) anos
pai
achega
b6de0caad6
Modificáronse 22 ficheiros con 255 adicións e 126 borrados
  1. 3 3
      frontend/app_flowy/lib/plugin/plugin.dart
  2. 6 7
      frontend/app_flowy/lib/plugin/src/sandbox.dart
  3. 14 13
      frontend/app_flowy/lib/startup/tasks/load_plugin.dart
  4. 1 1
      frontend/app_flowy/lib/workspace/application/appearance.dart
  5. 1 1
      frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart
  6. 1 1
      frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart
  7. 6 0
      frontend/app_flowy/lib/workspace/domain/view_ext.dart
  8. 1 2
      frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart
  9. 5 11
      frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart
  10. 2 1
      frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart
  11. 4 10
      frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart
  12. 1 1
      frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart
  13. 1 1
      frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart
  14. 42 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart
  15. 6 3
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart
  16. 3 43
      frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs
  17. 1 0
      frontend/rust-lib/flowy-folder/src/services/view/controller.rs
  18. 1 0
      frontend/rust-lib/flowy-net/src/local_server/server.rs
  19. 17 1
      shared-lib/flowy-folder-data-model/src/entities/view.rs
  20. 135 27
      shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs
  21. 3 0
      shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto
  22. 1 0
      shared-lib/flowy-folder-data-model/src/user_default.rs

+ 3 - 3
frontend/app_flowy/lib/plugin/plugin.dart

@@ -8,7 +8,7 @@ import 'package:flutter/widgets.dart';
 
 export "./src/sandbox.dart";
 
-typedef PluginType = String;
+typedef PluginType = int;
 
 typedef PluginDataType = ViewDataType;
 
@@ -31,7 +31,7 @@ abstract class PluginBuilder {
 
   PluginType get pluginType;
 
-  ViewDataType get dataType;
+  ViewDataType get dataType => ViewDataType.PlainText;
 }
 
 abstract class PluginDisplay with NavigationItem {
@@ -50,7 +50,7 @@ void registerPlugin({required PluginBuilder builder}) {
   getIt<PluginSandbox>().registerPlugin(builder.pluginType, builder);
 }
 
-Plugin makePlugin({required String pluginType, dynamic data}) {
+Plugin makePlugin({required PluginType pluginType, dynamic data}) {
   final plugin = getIt<PluginSandbox>().buildPlugin(pluginType, data);
   return plugin;
 }

+ 6 - 7
frontend/app_flowy/lib/plugin/src/sandbox.dart

@@ -6,14 +6,14 @@ import '../plugin.dart';
 import 'runner.dart';
 
 class PluginSandbox {
-  final LinkedHashMap<String, PluginBuilder> _pluginMap = LinkedHashMap();
+  final LinkedHashMap<PluginType, PluginBuilder> _pluginMap = LinkedHashMap();
   late PluginRunner pluginRunner;
 
   PluginSandbox() {
     pluginRunner = PluginRunner();
   }
 
-  int indexOf(String pluginType) {
+  int indexOf(PluginType pluginType) {
     final index = _pluginMap.keys.toList().indexWhere((ty) => ty == pluginType);
     if (index == -1) {
       throw PlatformException(code: '-1', message: "Can't find the flowy plugin type: $pluginType");
@@ -21,20 +21,19 @@ class PluginSandbox {
     return index;
   }
 
-  Plugin buildPlugin(String pluginType, dynamic data) {
-    final index = indexOf(pluginType);
-    final plugin = _pluginMap[index]!.build(data);
+  Plugin buildPlugin(PluginType pluginType, dynamic data) {
+    final plugin = _pluginMap[pluginType]!.build(data);
     return plugin;
   }
 
-  void registerPlugin(String pluginType, PluginBuilder builder) {
+  void registerPlugin(PluginType pluginType, PluginBuilder builder) {
     if (_pluginMap.containsKey(pluginType)) {
       throw PlatformException(code: '-1', message: "$pluginType was registered before");
     }
     _pluginMap[pluginType] = builder;
   }
 
-  List<String> get supportPluginTypes => _pluginMap.keys.toList();
+  List<int> get supportPluginTypes => _pluginMap.keys.toList();
 
   List<PluginBuilder> get builders => _pluginMap.values.toList();
 }

+ 14 - 13
frontend/app_flowy/lib/startup/tasks/load_plugin.dart

@@ -4,24 +4,27 @@ import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dar
 import 'package:app_flowy/workspace/presentation/stack_page/doc/doc_stack_page.dart';
 import 'package:app_flowy/workspace/presentation/stack_page/trash/trash_page.dart';
 
-enum DefaultPluginEnum {
+enum DefaultPlugin {
+  quillEditor,
   blank,
   trash,
 }
 
-extension FlowyDefaultPluginExt on DefaultPluginEnum {
-  String type() {
+extension FlowyDefaultPluginExt on DefaultPlugin {
+  int type() {
     switch (this) {
-      case DefaultPluginEnum.blank:
-        return "Blank";
-      case DefaultPluginEnum.trash:
-        return "Trash";
+      case DefaultPlugin.quillEditor:
+        return 0;
+      case DefaultPlugin.blank:
+        return 1;
+      case DefaultPlugin.trash:
+        return 2;
     }
   }
 }
 
-bool isDefaultPlugin(String pluginType) {
-  return DefaultPluginEnum.values.map((e) => e.type()).contains(pluginType);
+bool isDefaultPlugin(PluginType pluginType) {
+  return DefaultPlugin.values.map((e) => e.type()).contains(pluginType);
 }
 
 class PluginLoadTask extends LaunchTask {
@@ -30,10 +33,8 @@ class PluginLoadTask extends LaunchTask {
 
   @override
   Future<void> initialize(LaunchContext context) async {
-    registerPlugin(builder: DocumentPluginBuilder());
-
-    registerPlugin(builder: TrashPluginBuilder());
-
     registerPlugin(builder: BlankPluginBuilder());
+    registerPlugin(builder: TrashPluginBuilder());
+    registerPlugin(builder: DocumentPluginBuilder());
   }
 }

+ 1 - 1
frontend/app_flowy/lib/workspace/application/appearance.dart

@@ -48,7 +48,7 @@ class AppearanceSettingModel extends ChangeNotifier with EquatableMixin {
   void setLocale(BuildContext context, Locale newLocale) {
     if (_locale != newLocale) {
       if (!context.supportedLocales.contains(newLocale)) {
-        Log.error("Unsupported locale: $newLocale");
+        Log.warn("Unsupported locale: $newLocale");
         newLocale = const Locale('en');
         Log.debug("Fallback to locale: $newLocale");
       }

+ 1 - 1
frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart

@@ -100,6 +100,6 @@ class MenuState with _$MenuState {
         isCollapse: false,
         apps: none(),
         successOrFailure: left(unit),
-        plugin: makePlugin(pluginType: DefaultPluginEnum.blank.type()),
+        plugin: makePlugin(pluginType: DefaultPlugin.blank.type()),
       );
 }

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

@@ -40,7 +40,7 @@ class HomeStackNotifier extends ChangeNotifier {
 
   Widget get titleWidget => _plugin.display.leftBarItem;
 
-  HomeStackNotifier({Plugin? plugin}) : _plugin = plugin ?? makePlugin(pluginType: DefaultPluginEnum.blank.type());
+  HomeStackNotifier({Plugin? plugin}) : _plugin = plugin ?? makePlugin(pluginType: DefaultPlugin.blank.type());
 
   set plugin(Plugin newPlugin) {
     if (newPlugin.pluginId == _plugin.pluginId) {

+ 6 - 0
frontend/app_flowy/lib/workspace/domain/view_ext.dart

@@ -1,3 +1,4 @@
+import 'package:app_flowy/plugin/plugin.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
 import 'package:flutter/material.dart';
@@ -41,4 +42,9 @@ extension ViewExtension on View {
     final Widget widget = svg(thumbnail, color: iconColor);
     return widget;
   }
+
+  Plugin plugin() {
+    final plugin = makePlugin(pluginType: pluginType, data: this);
+    return plugin;
+  }
 }

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

@@ -13,7 +13,6 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/protobuf.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:styled_widget/styled_widget.dart';
-import 'package:app_flowy/workspace/domain/view_ext.dart';
 
 import 'home_layout.dart';
 
@@ -110,7 +109,7 @@ class _HomeScreenState extends State<HomeScreen> {
   Widget _buildHomeMenu({required HomeLayout layout, required BuildContext context}) {
     if (initialView == null && widget.workspaceSetting.hasLatestView()) {
       initialView = widget.workspaceSetting.latestView;
-      final plugin = makePlugin(pluginType: "RichText", data: initialView);
+      final plugin = makePlugin(pluginType: initialView!.pluginType, data: initialView);
       getIt<HomeStackManager>().setPlugin(plugin);
     }
 

+ 5 - 11
frontend/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart

@@ -1,14 +1,13 @@
 import 'package:app_flowy/startup/tasks/load_plugin.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pbenum.dart';
 import 'package:flutter/material.dart';
 
 import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'package:app_flowy/plugin/plugin.dart';
 import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
 
-class BlankPluginBuilder implements PluginBuilder {
+class BlankPluginBuilder extends PluginBuilder {
   @override
   Plugin build(dynamic data) {
     return BlankPagePlugin(pluginType: pluginType);
@@ -18,19 +17,14 @@ class BlankPluginBuilder implements PluginBuilder {
   String get pluginName => "Blank";
 
   @override
-  PluginType get pluginType => DefaultPluginEnum.blank.type();
-
-  @override
-  ViewDataType get dataType => ViewDataType.PlainText;
+  PluginType get pluginType => DefaultPlugin.blank.type();
 }
 
 class BlankPagePlugin implements Plugin {
-  late PluginType _pluginType;
+  final PluginType _pluginType;
   BlankPagePlugin({
-    required String pluginType,
-  }) {
-    _pluginType = pluginType;
-  }
+    required PluginType pluginType,
+  }) : _pluginType = pluginType;
 
   @override
   void dispose() {}

+ 2 - 1
frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart

@@ -1,5 +1,6 @@
 import 'package:app_flowy/plugin/plugin.dart';
 import 'package:app_flowy/startup/startup.dart';
+import 'package:app_flowy/startup/tasks/load_plugin.dart';
 import 'package:app_flowy/workspace/application/appearance.dart';
 import 'package:app_flowy/workspace/application/doc/share_bloc.dart';
 import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
@@ -38,7 +39,7 @@ class DocumentPluginBuilder implements PluginBuilder {
   String get pluginName => "Doc";
 
   @override
-  PluginType get pluginType => "RichText";
+  PluginType get pluginType => DefaultPlugin.quillEditor.type();
 
   @override
   ViewDataType get dataType => ViewDataType.RichText;

+ 4 - 10
frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart

@@ -14,7 +14,6 @@ import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
-import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pbenum.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:styled_widget/styled_widget.dart';
@@ -22,7 +21,7 @@ import 'package:app_flowy/generated/locale_keys.g.dart';
 
 import 'widget/trash_header.dart';
 
-class TrashPluginBuilder implements PluginBuilder {
+class TrashPluginBuilder extends PluginBuilder {
   @override
   Plugin build(dynamic data) {
     return TrashPlugin(pluginType: pluginType);
@@ -32,18 +31,13 @@ class TrashPluginBuilder implements PluginBuilder {
   String get pluginName => "Trash";
 
   @override
-  PluginType get pluginType => DefaultPluginEnum.trash.type();
-
-  @override
-  ViewDataType get dataType => ViewDataType.PlainText;
+  PluginType get pluginType => DefaultPlugin.trash.type();
 }
 
 class TrashPlugin implements Plugin {
-  late PluginType _pluginType;
+  final PluginType _pluginType;
 
-  TrashPlugin({required PluginType pluginType}) {
-    _pluginType = pluginType;
-  }
+  TrashPlugin({required PluginType pluginType}) : _pluginType = pluginType;
 
   @override
   void dispose() {}

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart

@@ -106,7 +106,7 @@ class ViewSectionNotifier with ChangeNotifier {
 
     if (view != null) {
       WidgetsBinding.instance?.addPostFrameCallback((_) {
-        getIt<HomeStackManager>().setPlugin(view.stackContext());
+        getIt<HomeStackManager>().setPlugin(view.plugin());
       });
     } else {
       // do nothing

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

@@ -23,7 +23,7 @@ class MenuTrash extends StatelessWidget {
       child: InkWell(
         onTap: () {
           Provider.of<MenuSharedState>(context, listen: false).selectedView.value = null;
-          getIt<HomeStackManager>().setPlugin(makePlugin(pluginType: DefaultPluginEnum.trash.type()));
+          getIt<HomeStackManager>().setPlugin(makePlugin(pluginType: DefaultPlugin.trash.type()));
         },
         child: _render(context),
       ),

+ 42 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart

@@ -27,6 +27,7 @@ class View extends $pb.GeneratedMessage {
     ..aInt64(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'createTime')
     ..aOS(10, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extData')
     ..aOS(11, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail')
+    ..a<$core.int>(12, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'pluginType', $pb.PbFieldType.O3)
     ..hasRequiredFields = false
   ;
 
@@ -43,6 +44,7 @@ class View extends $pb.GeneratedMessage {
     $fixnum.Int64? createTime,
     $core.String? extData,
     $core.String? thumbnail,
+    $core.int? pluginType,
   }) {
     final _result = create();
     if (id != null) {
@@ -78,6 +80,9 @@ class View extends $pb.GeneratedMessage {
     if (thumbnail != null) {
       _result.thumbnail = thumbnail;
     }
+    if (pluginType != null) {
+      _result.pluginType = pluginType;
+    }
     return _result;
   }
   factory View.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
@@ -201,6 +206,15 @@ class View extends $pb.GeneratedMessage {
   $core.bool hasThumbnail() => $_has(10);
   @$pb.TagNumber(11)
   void clearThumbnail() => clearField(11);
+
+  @$pb.TagNumber(12)
+  $core.int get pluginType => $_getIZ(11);
+  @$pb.TagNumber(12)
+  set pluginType($core.int v) { $_setSignedInt32(11, v); }
+  @$pb.TagNumber(12)
+  $core.bool hasPluginType() => $_has(11);
+  @$pb.TagNumber(12)
+  void clearPluginType() => clearField(12);
 }
 
 class RepeatedView extends $pb.GeneratedMessage {
@@ -262,6 +276,7 @@ class CreateViewPayload extends $pb.GeneratedMessage {
     ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail')
     ..e<ViewDataType>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.RichText, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values)
     ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extData')
+    ..a<$core.int>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'pluginType', $pb.PbFieldType.O3)
     ..hasRequiredFields = false
   ;
 
@@ -273,6 +288,7 @@ class CreateViewPayload extends $pb.GeneratedMessage {
     $core.String? thumbnail,
     ViewDataType? dataType,
     $core.String? extData,
+    $core.int? pluginType,
   }) {
     final _result = create();
     if (belongToId != null) {
@@ -293,6 +309,9 @@ class CreateViewPayload extends $pb.GeneratedMessage {
     if (extData != null) {
       _result.extData = extData;
     }
+    if (pluginType != null) {
+      _result.pluginType = pluginType;
+    }
     return _result;
   }
   factory CreateViewPayload.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
@@ -372,6 +391,15 @@ class CreateViewPayload extends $pb.GeneratedMessage {
   $core.bool hasExtData() => $_has(5);
   @$pb.TagNumber(6)
   void clearExtData() => clearField(6);
+
+  @$pb.TagNumber(7)
+  $core.int get pluginType => $_getIZ(6);
+  @$pb.TagNumber(7)
+  set pluginType($core.int v) { $_setSignedInt32(6, v); }
+  @$pb.TagNumber(7)
+  $core.bool hasPluginType() => $_has(6);
+  @$pb.TagNumber(7)
+  void clearPluginType() => clearField(7);
 }
 
 class CreateViewParams extends $pb.GeneratedMessage {
@@ -384,6 +412,7 @@ class CreateViewParams extends $pb.GeneratedMessage {
     ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'extData')
     ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId')
     ..aOS(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data')
+    ..a<$core.int>(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'pluginType', $pb.PbFieldType.O3)
     ..hasRequiredFields = false
   ;
 
@@ -397,6 +426,7 @@ class CreateViewParams extends $pb.GeneratedMessage {
     $core.String? extData,
     $core.String? viewId,
     $core.String? data,
+    $core.int? pluginType,
   }) {
     final _result = create();
     if (belongToId != null) {
@@ -423,6 +453,9 @@ class CreateViewParams extends $pb.GeneratedMessage {
     if (data != null) {
       _result.data = data;
     }
+    if (pluginType != null) {
+      _result.pluginType = pluginType;
+    }
     return _result;
   }
   factory CreateViewParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
@@ -517,6 +550,15 @@ class CreateViewParams extends $pb.GeneratedMessage {
   $core.bool hasData() => $_has(7);
   @$pb.TagNumber(8)
   void clearData() => clearField(8);
+
+  @$pb.TagNumber(9)
+  $core.int get pluginType => $_getIZ(8);
+  @$pb.TagNumber(9)
+  set pluginType($core.int v) { $_setSignedInt32(8, v); }
+  @$pb.TagNumber(9)
+  $core.bool hasPluginType() => $_has(8);
+  @$pb.TagNumber(9)
+  void clearPluginType() => clearField(9);
 }
 
 class ViewId extends $pb.GeneratedMessage {

+ 6 - 3
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart

@@ -34,11 +34,12 @@ const View$json = const {
     const {'1': 'create_time', '3': 9, '4': 1, '5': 3, '10': 'createTime'},
     const {'1': 'ext_data', '3': 10, '4': 1, '5': 9, '10': 'extData'},
     const {'1': 'thumbnail', '3': 11, '4': 1, '5': 9, '10': 'thumbnail'},
+    const {'1': 'plugin_type', '3': 12, '4': 1, '5': 5, '10': 'pluginType'},
   ],
 };
 
 /// Descriptor for `View`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List viewDescriptor = $convert.base64Decode('CgRWaWV3Eg4KAmlkGAEgASgJUgJpZBIgCgxiZWxvbmdfdG9faWQYAiABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgDIAEoCVIEbmFtZRISCgRkZXNjGAQgASgJUgRkZXNjEioKCWRhdGFfdHlwZRgFIAEoDjINLlZpZXdEYXRhVHlwZVIIZGF0YVR5cGUSGAoHdmVyc2lvbhgGIAEoA1IHdmVyc2lvbhItCgpiZWxvbmdpbmdzGAcgASgLMg0uUmVwZWF0ZWRWaWV3UgpiZWxvbmdpbmdzEiMKDW1vZGlmaWVkX3RpbWUYCCABKANSDG1vZGlmaWVkVGltZRIfCgtjcmVhdGVfdGltZRgJIAEoA1IKY3JlYXRlVGltZRIZCghleHRfZGF0YRgKIAEoCVIHZXh0RGF0YRIcCgl0aHVtYm5haWwYCyABKAlSCXRodW1ibmFpbA==');
+final $typed_data.Uint8List viewDescriptor = $convert.base64Decode('CgRWaWV3Eg4KAmlkGAEgASgJUgJpZBIgCgxiZWxvbmdfdG9faWQYAiABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgDIAEoCVIEbmFtZRISCgRkZXNjGAQgASgJUgRkZXNjEioKCWRhdGFfdHlwZRgFIAEoDjINLlZpZXdEYXRhVHlwZVIIZGF0YVR5cGUSGAoHdmVyc2lvbhgGIAEoA1IHdmVyc2lvbhItCgpiZWxvbmdpbmdzGAcgASgLMg0uUmVwZWF0ZWRWaWV3UgpiZWxvbmdpbmdzEiMKDW1vZGlmaWVkX3RpbWUYCCABKANSDG1vZGlmaWVkVGltZRIfCgtjcmVhdGVfdGltZRgJIAEoA1IKY3JlYXRlVGltZRIZCghleHRfZGF0YRgKIAEoCVIHZXh0RGF0YRIcCgl0aHVtYm5haWwYCyABKAlSCXRodW1ibmFpbBIfCgtwbHVnaW5fdHlwZRgMIAEoBVIKcGx1Z2luVHlwZQ==');
 @$core.Deprecated('Use repeatedViewDescriptor instead')
 const RepeatedView$json = const {
   '1': 'RepeatedView',
@@ -59,6 +60,7 @@ const CreateViewPayload$json = const {
     const {'1': 'thumbnail', '3': 4, '4': 1, '5': 9, '9': 0, '10': 'thumbnail'},
     const {'1': 'data_type', '3': 5, '4': 1, '5': 14, '6': '.ViewDataType', '10': 'dataType'},
     const {'1': 'ext_data', '3': 6, '4': 1, '5': 9, '10': 'extData'},
+    const {'1': 'plugin_type', '3': 7, '4': 1, '5': 5, '10': 'pluginType'},
   ],
   '8': const [
     const {'1': 'one_of_thumbnail'},
@@ -66,7 +68,7 @@ const CreateViewPayload$json = const {
 };
 
 /// Descriptor for `CreateViewPayload`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List createViewPayloadDescriptor = $convert.base64Decode('ChFDcmVhdGVWaWV3UGF5bG9hZBIgCgxiZWxvbmdfdG9faWQYASABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEh4KCXRodW1ibmFpbBgEIAEoCUgAUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIZCghleHRfZGF0YRgGIAEoCVIHZXh0RGF0YUISChBvbmVfb2ZfdGh1bWJuYWls');
+final $typed_data.Uint8List createViewPayloadDescriptor = $convert.base64Decode('ChFDcmVhdGVWaWV3UGF5bG9hZBIgCgxiZWxvbmdfdG9faWQYASABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEh4KCXRodW1ibmFpbBgEIAEoCUgAUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIZCghleHRfZGF0YRgGIAEoCVIHZXh0RGF0YRIfCgtwbHVnaW5fdHlwZRgHIAEoBVIKcGx1Z2luVHlwZUISChBvbmVfb2ZfdGh1bWJuYWls');
 @$core.Deprecated('Use createViewParamsDescriptor instead')
 const CreateViewParams$json = const {
   '1': 'CreateViewParams',
@@ -79,11 +81,12 @@ const CreateViewParams$json = const {
     const {'1': 'ext_data', '3': 6, '4': 1, '5': 9, '10': 'extData'},
     const {'1': 'view_id', '3': 7, '4': 1, '5': 9, '10': 'viewId'},
     const {'1': 'data', '3': 8, '4': 1, '5': 9, '10': 'data'},
+    const {'1': 'plugin_type', '3': 9, '4': 1, '5': 5, '10': 'pluginType'},
   ],
 };
 
 /// Descriptor for `CreateViewParams`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIZCghleHRfZGF0YRgGIAEoCVIHZXh0RGF0YRIXCgd2aWV3X2lkGAcgASgJUgZ2aWV3SWQSEgoEZGF0YRgIIAEoCVIEZGF0YQ==');
+final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIZCghleHRfZGF0YRgGIAEoCVIHZXh0RGF0YRIXCgd2aWV3X2lkGAcgASgJUgZ2aWV3SWQSEgoEZGF0YRgIIAEoCVIEZGF0YRIfCgtwbHVnaW5fdHlwZRgJIAEoBVIKcGx1Z2luVHlwZQ==');
 @$core.Deprecated('Use viewIdDescriptor instead')
 const ViewId$json = const {
   '1': 'ViewId',

+ 3 - 43
frontend/rust-lib/flowy-folder/src/services/persistence/version_1/view_sql.rs

@@ -65,49 +65,6 @@ impl ViewTableSql {
     }
 }
 
-// pub(crate) fn read_views(
-//     belong_to_id: &str,
-//     is_trash: Option<bool>,
-//     conn: &SqliteConnection,
-// ) -> Result<RepeatedView, FlowyError> {
-//     let views = dsl::view_table
-//         .inner_join(trash_table::dsl::trash_table.on(trash_id.ne(view_table::
-// id)))         .filter(view_table::belong_to_id.eq(belong_to_id))
-//         .select((
-//             view_table::id,
-//             view_table::belong_to_id,
-//             view_table::name,
-//             view_table::desc,
-//             view_table::modified_time,
-//             view_table::create_time,
-//             view_table::thumbnail,
-//             view_table::view_type,
-//             view_table::version,
-//         ))
-//         .load(conn)?
-//         .into_iter()
-//         .map(
-//             |(id, belong_to_id, name, desc, create_time, modified_time,
-// thumbnail, view_type, version)| {                 ViewTable {
-//                     id,
-//                     belong_to_id,
-//                     name,
-//                     desc,
-//                     modified_time,
-//                     create_time,
-//                     thumbnail,
-//                     view_type,
-//                     version,
-//                     is_trash: false,
-//                 }
-//                 .into()
-//             },
-//         )
-//         .collect::<Vec<View>>();
-//
-//     Ok(RepeatedView { items: views })
-// }
-
 #[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)]
 #[belongs_to(AppTable, foreign_key = "belong_to_id")]
 #[table_name = "view_table"]
@@ -165,6 +122,9 @@ impl std::convert::From<ViewTable> for View {
             create_time: table.create_time,
             ext_data: "".to_string(),
             thumbnail: table.thumbnail,
+            // Store the view in ViewTable was deprecated since v0.0.2.
+            // No need worry about plugin_type.
+            plugin_type: 0,
         }
     }
 }

+ 1 - 0
frontend/rust-lib/flowy-folder/src/services/view/controller.rs

@@ -178,6 +178,7 @@ impl ViewController {
             data: document_json,
             view_id: uuid_string(),
             ext_data: view.ext_data,
+            plugin_type: view.plugin_type,
         };
 
         let _ = self.create_view_from_params(duplicate_params).await?;

+ 1 - 0
frontend/rust-lib/flowy-net/src/local_server/server.rs

@@ -307,6 +307,7 @@ impl FolderCouldServiceV1 for LocalServer {
             create_time: time,
             ext_data: params.ext_data,
             thumbnail: params.thumbnail,
+            plugin_type: params.plugin_type,
         };
         FutureResult::new(async { Ok(view) })
     }

+ 17 - 1
shared-lib/flowy-folder-data-model/src/entities/view.rs

@@ -48,6 +48,14 @@ pub struct View {
 
     #[pb(index = 11)]
     pub thumbnail: String,
+
+    #[pb(index = 12)]
+    #[serde(default = "default_plugin_type")]
+    pub plugin_type: i32,
+}
+
+fn default_plugin_type() -> i32 {
+    0
 }
 
 #[derive(Eq, PartialEq, Debug, Default, ProtoBuf, Clone, Serialize, Deserialize)]
@@ -115,6 +123,9 @@ pub struct CreateViewPayload {
 
     #[pb(index = 6)]
     pub ext_data: String,
+
+    #[pb(index = 7)]
+    pub plugin_type: i32,
 }
 
 #[derive(Default, ProtoBuf, Debug, Clone)]
@@ -142,6 +153,9 @@ pub struct CreateViewParams {
 
     #[pb(index = 8)]
     pub data: String,
+
+    #[pb(index = 9)]
+    pub plugin_type: i32,
 }
 
 impl TryInto<CreateViewParams> for CreateViewPayload {
@@ -156,6 +170,7 @@ impl TryInto<CreateViewParams> for CreateViewPayload {
             None => "".to_string(),
             Some(thumbnail) => ViewThumbnail::parse(thumbnail)?.0,
         };
+        let data = "".to_string();
 
         Ok(CreateViewParams {
             belong_to_id,
@@ -165,7 +180,8 @@ impl TryInto<CreateViewParams> for CreateViewPayload {
             thumbnail,
             ext_data,
             view_id,
-            data: "".to_string(),
+            data,
+            plugin_type: self.plugin_type,
         })
     }
 }

+ 135 - 27
shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs

@@ -37,6 +37,7 @@ pub struct View {
     pub create_time: i64,
     pub ext_data: ::std::string::String,
     pub thumbnail: ::std::string::String,
+    pub plugin_type: i32,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
@@ -301,6 +302,21 @@ impl View {
     pub fn take_thumbnail(&mut self) -> ::std::string::String {
         ::std::mem::replace(&mut self.thumbnail, ::std::string::String::new())
     }
+
+    // int32 plugin_type = 12;
+
+
+    pub fn get_plugin_type(&self) -> i32 {
+        self.plugin_type
+    }
+    pub fn clear_plugin_type(&mut self) {
+        self.plugin_type = 0;
+    }
+
+    // Param is passed by value, moved
+    pub fn set_plugin_type(&mut self, v: i32) {
+        self.plugin_type = v;
+    }
 }
 
 impl ::protobuf::Message for View {
@@ -362,6 +378,13 @@ impl ::protobuf::Message for View {
                 11 => {
                     ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.thumbnail)?;
                 },
+                12 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeVarint {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    let tmp = is.read_int32()?;
+                    self.plugin_type = tmp;
+                },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
                 },
@@ -408,6 +431,9 @@ impl ::protobuf::Message for View {
         if !self.thumbnail.is_empty() {
             my_size += ::protobuf::rt::string_size(11, &self.thumbnail);
         }
+        if self.plugin_type != 0 {
+            my_size += ::protobuf::rt::value_size(12, self.plugin_type, ::protobuf::wire_format::WireTypeVarint);
+        }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
         my_size
@@ -449,6 +475,9 @@ impl ::protobuf::Message for View {
         if !self.thumbnail.is_empty() {
             os.write_string(11, &self.thumbnail)?;
         }
+        if self.plugin_type != 0 {
+            os.write_int32(12, self.plugin_type)?;
+        }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
     }
@@ -542,6 +571,11 @@ impl ::protobuf::Message for View {
                 |m: &View| { &m.thumbnail },
                 |m: &mut View| { &mut m.thumbnail },
             ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>(
+                "plugin_type",
+                |m: &View| { &m.plugin_type },
+                |m: &mut View| { &mut m.plugin_type },
+            ));
             ::protobuf::reflect::MessageDescriptor::new_pb_name::<View>(
                 "View",
                 fields,
@@ -569,6 +603,7 @@ impl ::protobuf::Clear for View {
         self.create_time = 0;
         self.ext_data.clear();
         self.thumbnail.clear();
+        self.plugin_type = 0;
         self.unknown_fields.clear();
     }
 }
@@ -759,6 +794,7 @@ pub struct CreateViewPayload {
     pub desc: ::std::string::String,
     pub data_type: ViewDataType,
     pub ext_data: ::std::string::String,
+    pub plugin_type: i32,
     // message oneof groups
     pub one_of_thumbnail: ::std::option::Option<CreateViewPayload_oneof_one_of_thumbnail>,
     // special fields
@@ -949,6 +985,21 @@ impl CreateViewPayload {
     pub fn take_ext_data(&mut self) -> ::std::string::String {
         ::std::mem::replace(&mut self.ext_data, ::std::string::String::new())
     }
+
+    // int32 plugin_type = 7;
+
+
+    pub fn get_plugin_type(&self) -> i32 {
+        self.plugin_type
+    }
+    pub fn clear_plugin_type(&mut self) {
+        self.plugin_type = 0;
+    }
+
+    // Param is passed by value, moved
+    pub fn set_plugin_type(&mut self, v: i32) {
+        self.plugin_type = v;
+    }
 }
 
 impl ::protobuf::Message for CreateViewPayload {
@@ -981,6 +1032,13 @@ impl ::protobuf::Message for CreateViewPayload {
                 6 => {
                     ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.ext_data)?;
                 },
+                7 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeVarint {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    let tmp = is.read_int32()?;
+                    self.plugin_type = tmp;
+                },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
                 },
@@ -1008,6 +1066,9 @@ impl ::protobuf::Message for CreateViewPayload {
         if !self.ext_data.is_empty() {
             my_size += ::protobuf::rt::string_size(6, &self.ext_data);
         }
+        if self.plugin_type != 0 {
+            my_size += ::protobuf::rt::value_size(7, self.plugin_type, ::protobuf::wire_format::WireTypeVarint);
+        }
         if let ::std::option::Option::Some(ref v) = self.one_of_thumbnail {
             match v {
                 &CreateViewPayload_oneof_one_of_thumbnail::thumbnail(ref v) => {
@@ -1036,6 +1097,9 @@ impl ::protobuf::Message for CreateViewPayload {
         if !self.ext_data.is_empty() {
             os.write_string(6, &self.ext_data)?;
         }
+        if self.plugin_type != 0 {
+            os.write_int32(7, self.plugin_type)?;
+        }
         if let ::std::option::Option::Some(ref v) = self.one_of_thumbnail {
             match v {
                 &CreateViewPayload_oneof_one_of_thumbnail::thumbnail(ref v) => {
@@ -1111,6 +1175,11 @@ impl ::protobuf::Message for CreateViewPayload {
                 |m: &CreateViewPayload| { &m.ext_data },
                 |m: &mut CreateViewPayload| { &mut m.ext_data },
             ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>(
+                "plugin_type",
+                |m: &CreateViewPayload| { &m.plugin_type },
+                |m: &mut CreateViewPayload| { &mut m.plugin_type },
+            ));
             ::protobuf::reflect::MessageDescriptor::new_pb_name::<CreateViewPayload>(
                 "CreateViewPayload",
                 fields,
@@ -1133,6 +1202,7 @@ impl ::protobuf::Clear for CreateViewPayload {
         self.one_of_thumbnail = ::std::option::Option::None;
         self.data_type = ViewDataType::RichText;
         self.ext_data.clear();
+        self.plugin_type = 0;
         self.unknown_fields.clear();
     }
 }
@@ -1160,6 +1230,7 @@ pub struct CreateViewParams {
     pub ext_data: ::std::string::String,
     pub view_id: ::std::string::String,
     pub data: ::std::string::String,
+    pub plugin_type: i32,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
@@ -1372,6 +1443,21 @@ impl CreateViewParams {
     pub fn take_data(&mut self) -> ::std::string::String {
         ::std::mem::replace(&mut self.data, ::std::string::String::new())
     }
+
+    // int32 plugin_type = 9;
+
+
+    pub fn get_plugin_type(&self) -> i32 {
+        self.plugin_type
+    }
+    pub fn clear_plugin_type(&mut self) {
+        self.plugin_type = 0;
+    }
+
+    // Param is passed by value, moved
+    pub fn set_plugin_type(&mut self, v: i32) {
+        self.plugin_type = v;
+    }
 }
 
 impl ::protobuf::Message for CreateViewParams {
@@ -1407,6 +1493,13 @@ impl ::protobuf::Message for CreateViewParams {
                 8 => {
                     ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?;
                 },
+                9 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeVarint {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    let tmp = is.read_int32()?;
+                    self.plugin_type = tmp;
+                },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
                 },
@@ -1443,6 +1536,9 @@ impl ::protobuf::Message for CreateViewParams {
         if !self.data.is_empty() {
             my_size += ::protobuf::rt::string_size(8, &self.data);
         }
+        if self.plugin_type != 0 {
+            my_size += ::protobuf::rt::value_size(9, self.plugin_type, ::protobuf::wire_format::WireTypeVarint);
+        }
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
         my_size
@@ -1473,6 +1569,9 @@ impl ::protobuf::Message for CreateViewParams {
         if !self.data.is_empty() {
             os.write_string(8, &self.data)?;
         }
+        if self.plugin_type != 0 {
+            os.write_int32(9, self.plugin_type)?;
+        }
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
     }
@@ -1551,6 +1650,11 @@ impl ::protobuf::Message for CreateViewParams {
                 |m: &CreateViewParams| { &m.data },
                 |m: &mut CreateViewParams| { &mut m.data },
             ));
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>(
+                "plugin_type",
+                |m: &CreateViewParams| { &m.plugin_type },
+                |m: &mut CreateViewParams| { &mut m.plugin_type },
+            ));
             ::protobuf::reflect::MessageDescriptor::new_pb_name::<CreateViewParams>(
                 "CreateViewParams",
                 fields,
@@ -1575,6 +1679,7 @@ impl ::protobuf::Clear for CreateViewParams {
         self.ext_data.clear();
         self.view_id.clear();
         self.data.clear();
+        self.plugin_type = 0;
         self.unknown_fields.clear();
     }
 }
@@ -2765,7 +2870,7 @@ impl ::protobuf::reflect::ProtobufValue for ViewDataType {
 }
 
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\nview.proto\"\xd4\x02\n\x04View\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\
+    \n\nview.proto\"\xf5\x02\n\x04View\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\
     \x02id\x12\x20\n\x0cbelong_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\tdata_type\x18\x05\x20\x01(\x0e2\r.ViewDataTypeR\x08\
@@ -2773,32 +2878,35 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     elongings\x18\x07\x20\x01(\x0b2\r.RepeatedViewR\nbelongings\x12#\n\rmodi\
     fied_time\x18\x08\x20\x01(\x03R\x0cmodifiedTime\x12\x1f\n\x0bcreate_time\
     \x18\t\x20\x01(\x03R\ncreateTime\x12\x19\n\x08ext_data\x18\n\x20\x01(\tR\
-    \x07extData\x12\x1c\n\tthumbnail\x18\x0b\x20\x01(\tR\tthumbnail\"+\n\x0c\
-    RepeatedView\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.ViewR\x05items\
-    \"\xd8\x01\n\x11CreateViewPayload\x12\x20\n\x0cbelong_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\tdata_type\x18\x05\x20\x01(\x0e2\r.Vie\
-    wDataTypeR\x08dataType\x12\x19\n\x08ext_data\x18\x06\x20\x01(\tR\x07extD\
-    ataB\x12\n\x10one_of_thumbnail\"\xee\x01\n\x10CreateViewParams\x12\x20\n\
-    \x0cbelong_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\x1c\n\tthumbnail\x18\x04\x20\x01(\tR\tthumbnail\x12*\n\tdata_type\
-    \x18\x05\x20\x01(\x0e2\r.ViewDataTypeR\x08dataType\x12\x19\n\x08ext_data\
-    \x18\x06\x20\x01(\tR\x07extData\x12\x17\n\x07view_id\x18\x07\x20\x01(\tR\
-    \x06viewId\x12\x12\n\x04data\x18\x08\x20\x01(\tR\x04data\"\x1e\n\x06View\
-    Id\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"&\n\x0eRepeatedViewI\
-    d\x12\x14\n\x05items\x18\x01\x20\x03(\tR\x05items\"\xaa\x01\n\x11UpdateV\
-    iewPayload\x12\x17\n\x07view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\
-    \x04name\x18\x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\
-    \x01(\tH\x01R\x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthu\
-    mbnailB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnai\
-    l\"\xa9\x01\n\x10UpdateViewParams\x12\x17\n\x07view_id\x18\x01\x20\x01(\
-    \tR\x06viewId\x12\x14\n\x04name\x18\x02\x20\x01(\tH\0R\x04name\x12\x14\n\
-    \x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12\x1e\n\tthumbnail\x18\x04\
-    \x20\x01(\tH\x02R\tthumbnailB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\
-    \x12\n\x10one_of_thumbnail*+\n\x0cViewDataType\x12\x0c\n\x08RichText\x10\
-    \0\x12\r\n\tPlainText\x10\x01b\x06proto3\
+    \x07extData\x12\x1c\n\tthumbnail\x18\x0b\x20\x01(\tR\tthumbnail\x12\x1f\
+    \n\x0bplugin_type\x18\x0c\x20\x01(\x05R\npluginType\"+\n\x0cRepeatedView\
+    \x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.ViewR\x05items\"\xf9\x01\n\
+    \x11CreateViewPayload\x12\x20\n\x0cbelong_to_id\x18\x01\x20\x01(\tR\nbel\
+    ongToId\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\tdata_type\x18\x05\x20\x01(\x0e2\r.ViewDataTypeR\x08d\
+    ataType\x12\x19\n\x08ext_data\x18\x06\x20\x01(\tR\x07extData\x12\x1f\n\
+    \x0bplugin_type\x18\x07\x20\x01(\x05R\npluginTypeB\x12\n\x10one_of_thumb\
+    nail\"\x8f\x02\n\x10CreateViewParams\x12\x20\n\x0cbelong_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\x1c\n\tthumbnail\x18\
+    \x04\x20\x01(\tR\tthumbnail\x12*\n\tdata_type\x18\x05\x20\x01(\x0e2\r.Vi\
+    ewDataTypeR\x08dataType\x12\x19\n\x08ext_data\x18\x06\x20\x01(\tR\x07ext\
+    Data\x12\x17\n\x07view_id\x18\x07\x20\x01(\tR\x06viewId\x12\x12\n\x04dat\
+    a\x18\x08\x20\x01(\tR\x04data\x12\x1f\n\x0bplugin_type\x18\t\x20\x01(\
+    \x05R\npluginType\"\x1e\n\x06ViewId\x12\x14\n\x05value\x18\x01\x20\x01(\
+    \tR\x05value\"&\n\x0eRepeatedViewId\x12\x14\n\x05items\x18\x01\x20\x03(\
+    \tR\x05items\"\xaa\x01\n\x11UpdateViewPayload\x12\x17\n\x07view_id\x18\
+    \x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\x02\x20\x01(\tH\0R\x04n\
+    ame\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12\x1e\n\tthumbn\
+    ail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\x0bone_of_nameB\r\n\x0bone_\
+    of_descB\x12\n\x10one_of_thumbnail\"\xa9\x01\n\x10UpdateViewParams\x12\
+    \x17\n\x07view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\
+    \x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\
+    \x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\
+    \x0bone_of_nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnail*+\n\x0cVi\
+    ewDataType\x12\x0c\n\x08RichText\x10\0\x12\r\n\tPlainText\x10\x01b\x06pr\
+    oto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 3 - 0
shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto

@@ -12,6 +12,7 @@ message View {
     int64 create_time = 9;
     string ext_data = 10;
     string thumbnail = 11;
+    int32 plugin_type = 12;
 }
 message RepeatedView {
     repeated View items = 1;
@@ -23,6 +24,7 @@ message CreateViewPayload {
     oneof one_of_thumbnail { string thumbnail = 4; };
     ViewDataType data_type = 5;
     string ext_data = 6;
+    int32 plugin_type = 7;
 }
 message CreateViewParams {
     string belong_to_id = 1;
@@ -33,6 +35,7 @@ message CreateViewParams {
     string ext_data = 6;
     string view_id = 7;
     string data = 8;
+    int32 plugin_type = 9;
 }
 message ViewId {
     string value = 1;

+ 1 - 0
shared-lib/flowy-folder-data-model/src/user_default.rs

@@ -63,5 +63,6 @@ fn create_default_view(app_id: String, time: chrono::DateTime<Utc>) -> View {
         create_time: time.timestamp(),
         ext_data: "".to_string(),
         thumbnail: "".to_string(),
+        plugin_type: 0,
     }
 }