feat: add new view_type, kanban

This commit is contained in:
appflowy 2022-02-26 17:28:23 +08:00
parent 01985848f9
commit c843571e3d
21 changed files with 87 additions and 89 deletions

View File

@ -1,9 +1,7 @@
import 'dart:convert';
import 'package:app_flowy/workspace/infrastructure/repos/document_repo.dart';
import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart';
import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/trash.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flutter_quill/flutter_quill.dart' show Document, Delta;
import 'package:flowy_sdk/log.dart';
@ -16,15 +14,13 @@ part 'doc_bloc.freezed.dart';
typedef FlutterQuillDocument = Document;
class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
final View view;
final DocumentRepository repo;
final ViewRepository repo;
final ViewListener listener;
final TrashRepo trashRepo;
late FlutterQuillDocument document;
StreamSubscription? _subscription;
DocumentBloc({
required this.view,
required this.repo,
required this.listener,
required this.trashRepo,
@ -41,12 +37,12 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
emit(state.copyWith(isDeleted: false));
},
deletePermanently: (DeletePermanently value) async {
final result = await trashRepo.deleteViews([Tuple2(view.id, TrashType.TrashView)]);
final result = await trashRepo.deleteViews([Tuple2(repo.view.id, TrashType.TrashView)]);
final newState = result.fold((l) => state.copyWith(forceClose: true), (r) => state);
emit(newState);
},
restorePage: (RestorePage value) async {
final result = await trashRepo.putback(view.id);
final result = await trashRepo.putback(repo.view.id);
final newState = result.fold((l) => state.copyWith(isDeleted: false), (r) => state);
emit(newState);
},
@ -107,7 +103,7 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
void _composeDelta(Delta composedDelta, Delta documentDelta) async {
final json = jsonEncode(composedDelta.toJson());
Log.debug("doc_id: $view.id - Send json: $json");
Log.debug("doc_id: $repo.view.id - Send json: $json");
final result = await repo.composeDelta(data: json);
result.fold((rustDoc) {

View File

@ -7,12 +7,12 @@ import 'package:freezed_annotation/freezed_annotation.dart';
part 'view_bloc.freezed.dart';
class ViewBloc extends Bloc<ViewEvent, ViewState> {
class ViewMenuBloc extends Bloc<ViewEvent, ViewState> {
final ViewRepository repo;
final ViewListener listener;
ViewBloc({
ViewMenuBloc({
required this.repo,
required this.listener,
}) : super(ViewState.init(repo.view)) {

View File

@ -17,7 +17,9 @@ extension SvgViewType on View {
String _imageNameForViewType(ViewType type) {
switch (type) {
case ViewType.Doc:
case ViewType.QuillDocument:
return "file_icon";
case ViewType.Kanban:
return "file_icon";
default:
return "file_icon";

View File

@ -9,7 +9,6 @@ import 'package:app_flowy/workspace/application/view/view_bloc.dart';
import 'package:app_flowy/workspace/application/workspace/welcome_bloc.dart';
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
import 'package:app_flowy/workspace/infrastructure/repos/app_repo.dart';
import 'package:app_flowy/workspace/infrastructure/repos/document_repo.dart';
import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart';
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart';
@ -48,8 +47,8 @@ class HomeDepsResolver {
(view, _) => ViewListener(view: view),
);
getIt.registerFactoryParam<ViewBloc, View, void>(
(view, _) => ViewBloc(
getIt.registerFactoryParam<ViewMenuBloc, View, void>(
(view, _) => ViewMenuBloc(
repo: ViewRepository(view: view),
listener: getIt<ViewListener>(param1: view),
),
@ -82,8 +81,7 @@ class HomeDepsResolver {
// Doc
getIt.registerFactoryParam<DocumentBloc, View, void>(
(view, _) => DocumentBloc(
view: view,
repo: DocumentRepository(docId: view.id),
repo: ViewRepository(view: view),
listener: getIt<ViewListener>(param1: view),
trashRepo: getIt<TrashRepo>(),
),

View File

@ -1,29 +0,0 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-collaboration/document_info.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
class DocumentRepository {
final String docId;
DocumentRepository({
required this.docId,
});
Future<Either<BlockDelta, FlowyError>> openDocument() {
final request = ViewId(value: docId);
return FolderEventOpenView(request).send();
}
Future<Either<BlockDelta, FlowyError>> composeDelta({required String data}) {
final request = BlockDelta.create()
..blockId = docId
..deltaJson = data;
return FolderEventApplyDocDelta(request).send();
}
Future<Either<Unit, FlowyError>> closeDocument() {
final request = ViewId(value: docId);
return FolderEventCloseView(request).send();
}
}

View File

@ -3,6 +3,7 @@ import 'dart:typed_data';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-collaboration/document_info.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
@ -45,6 +46,23 @@ class ViewRepository {
final request = ViewId(value: view.id);
return FolderEventDuplicateView(request).send();
}
Future<Either<BlockDelta, FlowyError>> openDocument() {
final request = ViewId(value: view.id);
return FolderEventOpenView(request).send();
}
Future<Either<BlockDelta, FlowyError>> composeDelta({required String data}) {
final request = BlockDelta.create()
..blockId = view.id
..deltaJson = data;
return FolderEventApplyDocDelta(request).send();
}
Future<Either<Unit, FlowyError>> closeDocument() {
final request = ViewId(value: view.id);
return FolderEventCloseView(request).send();
}
}
typedef DeleteNotifierValue = Either<View, FlowyError>;

View File

@ -64,10 +64,6 @@ class DocStackContext extends HomeStackContext<int, ShareActionWrapper> {
@override
ValueNotifier<int> get isUpdated => _isUpdated;
// List<NavigationItem> get navigationItems => naviStacks.map((stack) {
// return NavigationItemImpl(context: stack);
// }).toList();
List<NavigationItem> _makeNavigationItems() {
return [
this,

View File

@ -35,9 +35,7 @@ class TrashStackContext extends HomeStackContext {
HomeStackType get type => HomeStackType.trash;
@override
Widget buildWidget() {
return const TrashStackPage(key: ValueKey('TrashStackPage'));
}
Widget buildWidget() => const TrashStackPage(key: ValueKey('TrashStackPage'));
@override
List<NavigationItem> get navigationItems => [this];

View File

@ -36,12 +36,12 @@ class ViewSectionItem extends StatelessWidget {
final theme = context.watch<AppTheme>();
return MultiBlocProvider(
providers: [
BlocProvider(create: (ctx) => getIt<ViewBloc>(param1: view)..add(const ViewEvent.initial())),
BlocProvider(create: (ctx) => getIt<ViewMenuBloc>(param1: view)..add(const ViewEvent.initial())),
],
child: BlocBuilder<ViewBloc, ViewState>(
child: BlocBuilder<ViewMenuBloc, ViewState>(
builder: (context, state) {
return InkWell(
onTap: () => onSelected(context.read<ViewBloc>().state.view),
onTap: () => onSelected(context.read<ViewMenuBloc>().state.view),
child: FlowyHover(
config: HoverDisplayConfig(hoverColor: theme.bg3),
builder: (_, onHover) => _render(context, onHover, state, theme.iconColor),
@ -63,9 +63,9 @@ class ViewSectionItem extends StatelessWidget {
if (onHover || state.isEditing) {
children.add(
ViewDisclosureButton(
onTap: () => context.read<ViewBloc>().add(const ViewEvent.setIsEditing(true)),
onTap: () => context.read<ViewMenuBloc>().add(const ViewEvent.setIsEditing(true)),
onSelected: (action) {
context.read<ViewBloc>().add(const ViewEvent.setIsEditing(false));
context.read<ViewMenuBloc>().add(const ViewEvent.setIsEditing(false));
_handleAction(context, action);
},
),
@ -87,18 +87,18 @@ class ViewSectionItem extends StatelessWidget {
case ViewDisclosureAction.rename:
TextFieldDialog(
title: LocaleKeys.disclosureAction_rename.tr(),
value: context.read<ViewBloc>().state.view.name,
value: context.read<ViewMenuBloc>().state.view.name,
confirm: (newValue) {
context.read<ViewBloc>().add(ViewEvent.rename(newValue));
context.read<ViewMenuBloc>().add(ViewEvent.rename(newValue));
},
).show(context);
break;
case ViewDisclosureAction.delete:
context.read<ViewBloc>().add(const ViewEvent.delete());
context.read<ViewMenuBloc>().add(const ViewEvent.delete());
break;
case ViewDisclosureAction.duplicate:
context.read<ViewBloc>().add(const ViewEvent.duplicate());
context.read<ViewMenuBloc>().add(const ViewEvent.duplicate());
break;
}
});

View File

@ -11,11 +11,13 @@ import 'package:protobuf/protobuf.dart' as $pb;
class ViewType extends $pb.ProtobufEnum {
static const ViewType Blank = ViewType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Blank');
static const ViewType Doc = ViewType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Doc');
static const ViewType QuillDocument = ViewType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'QuillDocument');
static const ViewType Kanban = ViewType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Kanban');
static const $core.List<ViewType> values = <ViewType> [
Blank,
Doc,
QuillDocument,
Kanban,
];
static final $core.Map<$core.int, ViewType> _byValue = $pb.ProtobufEnum.initByValue(values);

View File

@ -13,12 +13,13 @@ const ViewType$json = const {
'1': 'ViewType',
'2': const [
const {'1': 'Blank', '2': 0},
const {'1': 'Doc', '2': 1},
const {'1': 'QuillDocument', '2': 1},
const {'1': 'Kanban', '2': 2},
],
};
/// Descriptor for `ViewType`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List viewTypeDescriptor = $convert.base64Decode('CghWaWV3VHlwZRIJCgVCbGFuaxAAEgcKA0RvYxAB');
final $typed_data.Uint8List viewTypeDescriptor = $convert.base64Decode('CghWaWV3VHlwZRIJCgVCbGFuaxAAEhEKDVF1aWxsRG9jdW1lbnQQARIKCgZLYW5iYW4QAg==');
@$core.Deprecated('Use viewDescriptor instead')
const View$json = const {
'1': 'View',

View File

@ -7,8 +7,8 @@ edition = "2018"
[lib]
name = "dart_ffi"
# this value will change depending on the target os
# default cdylib
crate-type = ["cdylib"]
# default staticlib
crate-type = ["staticlib"]
[dependencies]

View File

@ -127,8 +127,9 @@ pub(crate) struct ViewTable {
impl ViewTable {
pub fn new(view: View) -> Self {
let view_type = match view.view_type {
ViewType::Blank => ViewTableType::Docs,
ViewType::Doc => ViewTableType::Docs,
ViewType::Kanban => ViewTableType::Kanban,
ViewType::QuillDocument => ViewTableType::QuillDocument,
ViewType::Blank => ViewTableType::QuillDocument,
};
ViewTable {
@ -150,7 +151,8 @@ impl ViewTable {
impl std::convert::From<ViewTable> for View {
fn from(table: ViewTable) -> Self {
let view_type = match table.view_type {
ViewTableType::Docs => ViewType::Doc,
ViewTableType::QuillDocument => ViewType::QuillDocument,
ViewTableType::Kanban => ViewType::Kanban,
};
View {
@ -215,22 +217,24 @@ impl ViewChangeset {
#[repr(i32)]
#[sql_type = "Integer"]
pub enum ViewTableType {
Docs = 0,
QuillDocument = 0,
Kanban = 1,
}
impl std::default::Default for ViewTableType {
fn default() -> Self {
ViewTableType::Docs
ViewTableType::QuillDocument
}
}
impl std::convert::From<i32> for ViewTableType {
fn from(value: i32) -> Self {
match value {
0 => ViewTableType::Docs,
0 => ViewTableType::QuillDocument,
1 => ViewTableType::Kanban,
o => {
log::error!("Unsupported view type {}, fallback to ViewType::Docs", o);
ViewTableType::Docs
ViewTableType::QuillDocument
}
}
}

View File

@ -68,7 +68,14 @@ impl FolderTest {
let _ = sdk.init_user().await;
let mut workspace = create_workspace(&sdk, "FolderWorkspace", "Folder test workspace").await;
let mut app = create_app(&sdk, &workspace.id, "Folder App", "Folder test app").await;
let view = create_view(&sdk, &app.id, "Folder View", "Folder test view", ViewType::Doc).await;
let view = create_view(
&sdk,
&app.id,
"Folder View",
"Folder test view",
ViewType::QuillDocument,
)
.await;
app.belongings = RepeatedView {
items: vec![view.clone()],
};
@ -146,7 +153,7 @@ impl FolderTest {
}
FolderScript::CreateView { name, desc } => {
let view = create_view(sdk, &self.app.id, &name, &desc, ViewType::Doc).await;
let view = create_view(sdk, &self.app.id, &name, &desc, ViewType::QuillDocument).await;
self.view = view;
}
FolderScript::AssertView(view) => {

View File

@ -67,7 +67,7 @@ fn crate_log_filter(level: String) -> String {
filters.push(format!("flowy_folder={}", level));
filters.push(format!("flowy_user={}", level));
filters.push(format!("flowy_document={}", level));
filters.push(format!("flowy_collaboration={}", level));
// filters.push(format!("flowy_collaboration={}", level));
filters.push(format!("dart_notify={}", level));
filters.push(format!("lib_ot={}", level));
filters.push(format!("lib_ws={}", level));

View File

@ -88,7 +88,7 @@ async fn create_view(sdk: &FlowySDKTest, app_id: &str) -> View {
name: "View A".to_string(),
desc: "".to_string(),
thumbnail: Some("http://1.png".to_string()),
view_type: ViewType::Doc,
view_type: ViewType::QuillDocument,
};
let view = FolderEventBuilder::new(sdk.clone())

View File

@ -146,10 +146,9 @@ where
let object_id = self.object_id.clone();
let server_rev_id = self.rev_id();
tracing::Span::current().record("server_rev_id", &server_rev_id);
match server_rev_id.cmp(&client_rev_id) {
Ordering::Less => {
tracing::warn!("Client should not send ping and the server should pull the revisions from the client")
tracing::trace!("Client should not send ping and the server should pull the revisions from the client")
}
Ordering::Equal => tracing::trace!("{} is up to date.", object_id),
Ordering::Greater => {

View File

@ -65,7 +65,8 @@ impl std::convert::From<View> for Trash {
#[derive(Eq, PartialEq, Debug, ProtoBuf_Enum, Clone, Serialize, Deserialize)]
pub enum ViewType {
Blank = 0,
Doc = 1,
QuillDocument = 1,
Kanban = 2,
}
impl std::default::Default for ViewType {
@ -77,8 +78,9 @@ impl std::default::Default for ViewType {
impl std::convert::From<i32> for ViewType {
fn from(val: i32) -> Self {
match val {
1 => ViewType::Doc,
0 => ViewType::Blank,
1 => ViewType::QuillDocument,
2 => ViewType::Kanban,
_ => {
log::error!("Invalid view type: {}", val);
ViewType::Blank

View File

@ -2549,7 +2549,8 @@ impl ::protobuf::reflect::ProtobufValue for UpdateViewParams {
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum ViewType {
Blank = 0,
Doc = 1,
QuillDocument = 1,
Kanban = 2,
}
impl ::protobuf::ProtobufEnum for ViewType {
@ -2560,7 +2561,8 @@ impl ::protobuf::ProtobufEnum for ViewType {
fn from_i32(value: i32) -> ::std::option::Option<ViewType> {
match value {
0 => ::std::option::Option::Some(ViewType::Blank),
1 => ::std::option::Option::Some(ViewType::Doc),
1 => ::std::option::Option::Some(ViewType::QuillDocument),
2 => ::std::option::Option::Some(ViewType::Kanban),
_ => ::std::option::Option::None
}
}
@ -2568,7 +2570,8 @@ impl ::protobuf::ProtobufEnum for ViewType {
fn values() -> &'static [Self] {
static values: &'static [ViewType] = &[
ViewType::Blank,
ViewType::Doc,
ViewType::QuillDocument,
ViewType::Kanban,
];
values
}
@ -2626,8 +2629,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\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*\x1e\n\x08ViewType\x12\t\n\x05Blank\x10\0\x12\
\x07\n\x03Doc\x10\x01b\x06proto3\
\x12\n\x10one_of_thumbnail*4\n\x08ViewType\x12\t\n\x05Blank\x10\0\x12\
\x11\n\rQuillDocument\x10\x01\x12\n\n\x06Kanban\x10\x02b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -50,5 +50,6 @@ message UpdateViewParams {
}
enum ViewType {
Blank = 0;
Doc = 1;
QuillDocument = 1;
Kanban = 2;
}

View File

@ -49,7 +49,7 @@ fn create_default_view(app_id: String, time: chrono::DateTime<Utc>) -> View {
let view_id = uuid::Uuid::new_v4();
let name = "Read me".to_string();
let desc = "".to_string();
let view_type = ViewType::Doc;
let view_type = ViewType::QuillDocument;
View {
id: view_id.to_string(),