Skip to content

Commit

Permalink
Merge branch 'main' into release/0.7.9
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasXu0 committed Dec 26, 2024
2 parents db43fdf + 3959cdb commit 638d602
Show file tree
Hide file tree
Showing 24 changed files with 832 additions and 247 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -394,18 +394,24 @@ void main() {
isChecked: false,
);
tester.assertPhantomChecklistItemAtIndex(index: 1);
tester.assertPhantomChecklistItemContent("");

await tester.enterText(find.byType(PhantomChecklistItem), 'task 2');
await tester.pumpAndSettle();
await tester.simulateKeyEvent(LogicalKeyboardKey.enter);
await tester.pumpAndSettle(const Duration(milliseconds: 500));
await tester.hoverOnWidget(
find.byType(ChecklistRowDetailCell),
onHover: () async {
await tester.tapButton(find.byType(ChecklistItemControl));
},
);

tester.assertChecklistTaskInEditor(
index: 1,
name: "task 2",
isChecked: false,
);
tester.assertPhantomChecklistItemAtIndex(index: 2);
tester.assertPhantomChecklistItemContent("");

await tester.simulateKeyEvent(LogicalKeyboardKey.escape);
await tester.pumpAndSettle();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import 'dart:io';

import 'package:flutter/services.dart';

import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/block_menu/block_menu_button.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/clipboard_service.dart';
Expand All @@ -11,6 +9,7 @@ import 'package:appflowy/startup/startup.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:universal_platform/universal_platform.dart';
Expand All @@ -27,10 +26,13 @@ void main() {
await tester.pasteContent(
plainText: List.generate(lines, (index) => 'line $index').join('\n'),
(editorState) {
expect(editorState.document.root.children.length, 3);
expect(editorState.document.root.children.length, 1);
final text =
editorState.document.root.children.first.delta!.toPlainText();
final textLines = text.split('\n');
for (var i = 0; i < lines; i++) {
expect(
editorState.getNodeAtPath([i])!.delta!.toPlainText(),
textLines[i],
'line $i',
);
}
Expand Down Expand Up @@ -467,6 +469,44 @@ void main() {
expect(node.attributes[ImageBlockKeys.url], isNotEmpty);
});
});

const testMarkdownText = '''
# I'm h1
## I'm h2
### I'm h3
#### I'm h4
##### I'm h5
###### I'm h6''';

testWidgets('paste markdowns', (tester) async {
await tester.pasteContent(
plainText: testMarkdownText,
(editorState) {
final children = editorState.document.root.children;
expect(children.length, 6);
for (int i = 1; i <= children.length; i++) {
final text = children[i - 1].delta!.toPlainText();
expect(text, 'I\'m h$i');
}
},
);
});

testWidgets('paste markdowns as plain', (tester) async {
await tester.pasteContent(
plainText: testMarkdownText,
pasteAsPlain: true,
(editorState) {
final children = editorState.document.root.children;
expect(children.length, 6);
for (int i = 1; i <= children.length; i++) {
final text = children[i - 1].delta!.toPlainText();
final expectText = '${'#' * i} I\'m h$i';
expect(text, expectText);
}
},
);
});
}

extension on WidgetTester {
Expand All @@ -476,6 +516,7 @@ extension on WidgetTester {
String? plainText,
String? html,
String? inAppJson,
bool pasteAsPlain = false,
(String, Uint8List?)? image,
}) async {
await initializeAppFlowy();
Expand All @@ -502,6 +543,7 @@ extension on WidgetTester {
await simulateKeyEvent(
LogicalKeyboardKey.keyV,
isControlPressed: Platform.isLinux || Platform.isWindows,
isShiftPressed: pasteAsPlain,
isMetaPressed: Platform.isMacOS,
);
await pumpAndSettle();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ void main() {

// set clipboard data
final data = [
"123456\n",
...List.generate(100, (_) => "${generateRandomString(50)}\n"),
"1234567\n",
...List.generate(100, (_) => "${generateRandomString(50)}\n"),
"12345678\n",
...List.generate(100, (_) => "${generateRandomString(50)}\n"),
"123456\n\n",
...List.generate(100, (_) => "${generateRandomString(50)}\n\n"),
"1234567\n\n",
...List.generate(100, (_) => "${generateRandomString(50)}\n\n"),
"12345678\n\n",
...List.generate(100, (_) => "${generateRandomString(50)}\n\n"),
].join();
await getIt<ClipboardService>().setData(
ClipboardServiceData(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,12 @@ extension AppFlowyDatabaseTest on WidgetTester {
expect(phantom is PhantomChecklistItem, true);
}

void assertPhantomChecklistItemContent(String content) {
final phantom = find.byType(PhantomChecklistItem);
final text = find.text(content);
expect(find.descendant(of: phantom, matching: text), findsOneWidget);
}

Future<void> openFirstRowDetailPage() async {
await hoverOnFirstRowOfGrid();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import 'dart:async';

import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/document/application/document_data_pb_extension.dart';
import 'package:appflowy/plugins/document/application/prelude.dart';
import 'package:appflowy/shared/markdown_to_document.dart';
import 'package:appflowy/workspace/application/view/view_service.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_result/appflowy_result.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_chat_core/flutter_chat_core.dart';

class ChatEditDocumentService {
static Future<ViewPB?> saveMessagesToNewPage(
String chatPageName,
String parentViewId,
List<TextMessage> messages,
) async {
if (messages.isEmpty) {
return null;
}

// Convert messages to markdown and trim the last empty newline.
final completeMessage = messages.map((m) => m.text).join('\n').trimRight();
if (completeMessage.isEmpty) {
return null;
}

final document = customMarkdownToDocument(completeMessage);
final initialBytes =
DocumentDataPBFromTo.fromDocument(document)?.writeToBuffer();
if (initialBytes == null) {
Log.error('Failed to convert messages to document');
return null;
}

return ViewBackendService.createView(
name: LocaleKeys.chat_addToNewPageName.tr(args: [chatPageName]),
layoutType: ViewLayoutPB.Document,
parentViewId: parentViewId,
initialDataBytes: initialBytes,
).toNullable();
}

static Future<void> addMessageToPage(
String documentId,
TextMessage message,
) async {
if (message.text.isEmpty) {
Log.error('Message is empty');
return;
}

final bloc = DocumentBloc(
documentId: documentId,
saveToBlocMap: false,
)..add(const DocumentEvent.initial());

if (bloc.state.editorState == null) {
await bloc.stream.firstWhere((state) => state.editorState != null);
}

final editorState = bloc.state.editorState;
if (editorState == null) {
Log.error("Can't get EditorState of document");
return;
}

final messageDocument = customMarkdownToDocument(message.text);
if (messageDocument.isEmpty) {
Log.error('Failed to convert message to document');
return;
}

final lastNodeOrNull = editorState.document.root.children.lastOrNull;

final rootIsEmpty = lastNodeOrNull == null;
final isLastLineEmpty = lastNodeOrNull?.children.isNotEmpty == false &&
lastNodeOrNull?.delta?.isNotEmpty == false;

final nodes = [
if (rootIsEmpty || !isLastLineEmpty) paragraphNode(),
...messageDocument.root.children,
];
final insertPath = rootIsEmpty || listEquals(lastNodeOrNull.path, const [0])
? const [0]
: lastNodeOrNull.path.next;

final transaction = editorState.transaction..insertNodes(insertPath, nodes);
await editorState.apply(transaction);
await bloc.close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,8 @@ class ChatSource {
}

class ChatSettingsCubit extends Cubit<ChatSettingsState> {
ChatSettingsCubit({required this.chatId})
: super(ChatSettingsState.initial());
ChatSettingsCubit() : super(ChatSettingsState.initial());

final String chatId;
List<String> selectedSourceIds = [];
ChatSource? source;
List<ChatSource> selectedSources = [];
Expand Down
21 changes: 3 additions & 18 deletions frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import 'dart:async';
import 'dart:io';

import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/application/mobile_router.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
import 'package:appflowy/workspace/application/view/view_ext.dart';
import 'package:appflowy/workspace/application/view/view_service.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
Expand Down Expand Up @@ -36,6 +31,7 @@ import 'presentation/chat_welcome_page.dart';
import 'presentation/layout_define.dart';
import 'presentation/message/ai_text_message.dart';
import 'presentation/message/error_text_message.dart';
import 'presentation/message/message_util.dart';
import 'presentation/message/user_text_message.dart';
import 'presentation/scroll_to_bottom.dart';

Expand Down Expand Up @@ -355,19 +351,8 @@ class _ChatContentPage extends StatelessWidget {
} else {
final sidebarView =
await ViewBackendService.getView(metadata.id).toNullable();
if (sidebarView == null) {
return;
}
if (UniversalPlatform.isDesktop) {
getIt<TabsBloc>().add(
TabsEvent.openSecondaryPlugin(
plugin: sidebarView.plugin(),
),
);
} else {
if (context.mounted) {
unawaited(context.pushView(sidebarView));
}
if (context.mounted) {
openPageFromMessage(context, sidebarView);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ class _DesktopAIPromptInputState extends State<DesktopAIPromptInput> {
top: null,
child: TextFieldTapRegion(
child: _PromptBottomActions(
chatId: widget.chatId,
textController: textController,
overlayController: overlayController,
focusNode: focusNode,
Expand Down Expand Up @@ -483,7 +482,6 @@ class _FocusNextItemIntent extends Intent {

class _PromptBottomActions extends StatelessWidget {
const _PromptBottomActions({
required this.chatId,
required this.textController,
required this.overlayController,
required this.focusNode,
Expand All @@ -493,7 +491,6 @@ class _PromptBottomActions extends StatelessWidget {
required this.onUpdateSelectedSources,
});

final String chatId;
final TextEditingController textController;
final OverlayPortalController overlayController;
final FocusNode focusNode;
Expand Down Expand Up @@ -539,7 +536,6 @@ class _PromptBottomActions extends StatelessWidget {

Widget _selectSourcesButton(BuildContext context) {
return PromptInputDesktopSelectSourcesButton(
chatId: chatId,
onUpdateSelectedSources: onUpdateSelectedSources,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,6 @@ class _MobileAIPromptInputState extends State<MobileAIPromptInput> {
alignment: Alignment.bottomCenter,
padding: const EdgeInsets.only(bottom: 8.0),
child: _LeadingActions(
chatId: widget.chatId,
textController: textController,
// onMention: () {
// textController.text += '@';
Expand Down Expand Up @@ -303,12 +302,10 @@ class _MobileAIPromptInputState extends State<MobileAIPromptInput> {

class _LeadingActions extends StatelessWidget {
const _LeadingActions({
required this.chatId,
required this.textController,
required this.onUpdateSelectedSources,
});

final String chatId;
final TextEditingController textController;
final void Function(List<String>) onUpdateSelectedSources;

Expand All @@ -317,7 +314,6 @@ class _LeadingActions extends StatelessWidget {
return Material(
color: Theme.of(context).cardColor,
child: PromptInputMobileSelectSourcesButton(
chatId: chatId,
onUpdateSelectedSources: onUpdateSelectedSources,
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@ import 'select_sources_menu.dart';
class PromptInputMobileSelectSourcesButton extends StatefulWidget {
const PromptInputMobileSelectSourcesButton({
super.key,
required this.chatId,
required this.onUpdateSelectedSources,
});

final String chatId;
final void Function(List<String>) onUpdateSelectedSources;

@override
Expand All @@ -34,7 +32,7 @@ class PromptInputMobileSelectSourcesButton extends StatefulWidget {

class _PromptInputMobileSelectSourcesButtonState
extends State<PromptInputMobileSelectSourcesButton> {
late final cubit = ChatSettingsCubit(chatId: widget.chatId);
late final cubit = ChatSettingsCubit();

@override
void initState() {
Expand Down
Loading

0 comments on commit 638d602

Please sign in to comment.