feat: add cover migration for document (#1929)

* feat: add cover migration for document

* fix: should not delete the cover when selecting all

* fix: chinese characters for openai
This commit is contained in:
Lucas.Xu 2023-03-07 09:33:59 +08:00 committed by GitHub
parent 675c833f07
commit 7ff4cecd09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 35 deletions

View File

@ -1,15 +1,18 @@
import 'dart:convert';
import 'package:appflowy/plugins/document/presentation/plugins/cover/cover_node_widget.dart';
import 'package:appflowy/plugins/trash/application/trash_service.dart';
import 'package:appflowy/user/application/user_service.dart';
import 'package:appflowy/workspace/application/view/view_listener.dart';
import 'package:appflowy/plugins/document/application/doc_service.dart';
import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pbserver.dart';
import 'package:appflowy_editor/appflowy_editor.dart'
show EditorState, Document, Transaction;
show EditorState, Document, Transaction, Node;
import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/log.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:dartz/dartz.dart';
@ -78,29 +81,27 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
Future<void> _initial(Initial value, Emitter<DocumentState> emit) async {
final userProfile = await UserBackendService.getCurrentUserProfile();
if (userProfile.isRight()) {
emit(
return emit(
state.copyWith(
loadingState: DocumentLoadingState.finish(
right(userProfile.asRight()),
),
),
);
return;
}
final result = await _documentService.openDocument(view: view);
result.fold(
(documentData) {
final document = Document.fromJson(jsonDecode(documentData.content));
editorState = EditorState(document: document);
_listenOnDocumentChange();
return result.fold(
(documentData) async {
await _initEditorState(documentData).whenComplete(() {
emit(
state.copyWith(
loadingState: DocumentLoadingState.finish(left(unit)),
userProfilePB: userProfile.asLeft(),
),
);
});
},
(err) {
(err) async {
emit(
state.copyWith(
loadingState: DocumentLoadingState.finish(right(err)),
@ -127,8 +128,13 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
);
}
void _listenOnDocumentChange() {
_subscription = editorState?.transactionStream.listen((transaction) {
Future<void> _initEditorState(DocumentDataPB documentData) async {
final document = Document.fromJson(jsonDecode(documentData.content));
final editorState = EditorState(document: document);
this.editorState = editorState;
// listen on document change
_subscription = editorState.transactionStream.listen((transaction) {
final json = jsonEncode(TransactionAdaptor(transaction).toJson());
_documentService
.applyEdit(docId: view.id, operations: json)
@ -139,6 +145,15 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
);
});
});
// log
if (kDebugMode) {
editorState.logConfiguration.handler = (log) {
Log.debug(log);
};
}
// migration
final migration = DocumentMigration(editorState: editorState);
await migration.apply();
}
}
@ -215,3 +230,33 @@ class TransactionAdaptor {
return json;
}
}
class DocumentMigration {
const DocumentMigration({
required this.editorState,
});
final EditorState editorState;
/// Migrate the document to the latest version.
Future<void> apply() async {
final transaction = editorState.transaction;
// A temporary solution to migrate the document to the latest version.
// Once the editor is stable, we can remove this.
// cover plugin
if (editorState.document.nodeAtPath([0])?.type != kCoverType) {
transaction.insertNode(
[0],
Node(type: kCoverType),
);
}
transaction.afterSelection = null;
if (transaction.operations.isNotEmpty) {
editorState.apply(transaction);
}
}
}

View File

@ -91,7 +91,13 @@ class HttpOpenAIRepository implements OpenAIRepository {
);
if (response.statusCode == 200) {
return Right(TextCompletionResponse.fromJson(json.decode(response.body)));
return Right(
TextCompletionResponse.fromJson(
json.decode(
utf8.decode(response.bodyBytes),
),
),
);
} else {
return Left(OpenAIError.fromJson(json.decode(response.body)['error']));
}
@ -119,7 +125,13 @@ class HttpOpenAIRepository implements OpenAIRepository {
);
if (response.statusCode == 200) {
return Right(TextEditResponse.fromJson(json.decode(response.body)));
return Right(
TextEditResponse.fromJson(
json.decode(
utf8.decode(response.bodyBytes),
),
),
);
} else {
return Left(OpenAIError.fromJson(json.decode(response.body)['error']));
}

View File

@ -1,10 +1,9 @@
import 'package:appflowy/plugins/document/document.dart';
import 'package:appflowy/plugins/document/presentation/plugins/cover/cover_node_widget.dart';
import 'package:appflowy/startup/plugin/plugin.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/presentation/home/menu/app/header/import/import_panel.dart';
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
import 'package:appflowy_editor/appflowy_editor.dart' show Document, Node;
import 'package:appflowy_editor/appflowy_editor.dart' show Document;
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
@ -61,12 +60,7 @@ class AddButton extends StatelessWidget {
},
onSelected: (action, controller) {
if (action is AddButtonActionWrapper) {
Document? document;
if (action.pluginType == PluginType.editor) {
// initialize the document if needed.
document = buildInitialDocument();
}
onSelected(action.pluginBuilder, document);
onSelected(action.pluginBuilder, null);
}
if (action is ImportActionWrapper) {
showImportPanel(context, (document) {
@ -80,12 +74,6 @@ class AddButton extends StatelessWidget {
},
);
}
Document buildInitialDocument() {
final document = Document.empty();
document.insert([0], [Node(type: kCoverType)]);
return document;
}
}
class AddButtonActionWrapper extends ActionCell {

View File

@ -12,8 +12,9 @@ ShortcutEventHandler backspaceEventHandler = (editorState, event) {
nodes = selection.isBackward ? nodes : nodes.reversed.toList(growable: false);
selection = selection.isBackward ? selection : selection.reversed;
final textNodes = nodes.whereType<TextNode>().toList();
final List<Node> nonTextNodes =
nodes.where((node) => node is! TextNode).toList(growable: false);
final List<Node> nonTextNodes = nodes
.where((node) => node is! TextNode && node.selectable != null)
.toList(growable: false);
final transaction = editorState.transaction;
List<int>? cancelNumberListPath;