mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-11-02 11:04:02 +00:00
fix: unable to render code block in ai writer block (#6883)
* fix: unable to render code block in ai writer block * feat: enter to generate ai result
This commit is contained in:
parent
510d8357ee
commit
62c4a8c541
@ -1,5 +1,6 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:appflowy/shared/markdown_to_document.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@ -8,7 +9,7 @@ import 'package:synchronized/synchronized.dart';
|
||||
class MarkdownTextRobot {
|
||||
MarkdownTextRobot({
|
||||
required this.editorState,
|
||||
this.enableDebug = false,
|
||||
this.enableDebug = true,
|
||||
});
|
||||
|
||||
final EditorState editorState;
|
||||
@ -92,7 +93,7 @@ class MarkdownTextRobot {
|
||||
final transaction = editorState.transaction;
|
||||
|
||||
// Convert markdown and deep copy nodes
|
||||
final nodes = markdownToDocument(_markdownText).root.children.map(
|
||||
final nodes = customMarkdownToDocument(_markdownText).root.children.map(
|
||||
(node) => node.copyWith(),
|
||||
); // deep copy the nodes to avoid the linked entities being changed.
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@ import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:universal_platform/universal_platform.dart';
|
||||
|
||||
@ -107,6 +108,8 @@ class _AIWriterBlockComponentState extends State<AIWriterBlockComponent> {
|
||||
return null;
|
||||
}
|
||||
|
||||
bool isGenerating = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@ -134,34 +137,48 @@ class _AIWriterBlockComponentState extends State<AIWriterBlockComponent> {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final child = Card(
|
||||
elevation: 5,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const AIWriterBlockHeader(),
|
||||
const Space(0, 10),
|
||||
if (prompt.isEmpty && generationCount < 1) ...[
|
||||
_buildInputWidget(context),
|
||||
final child = Focus(
|
||||
onKeyEvent: (node, event) {
|
||||
if (event is! KeyDownEvent) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
if (event.logicalKey == LogicalKeyboardKey.enter) {
|
||||
if (!isGenerating) {
|
||||
_onGenerate();
|
||||
}
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
return KeyEventResult.ignored;
|
||||
},
|
||||
child: Card(
|
||||
elevation: 5,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const AIWriterBlockHeader(),
|
||||
const Space(0, 10),
|
||||
AIWriterBlockInputField(
|
||||
onGenerate: _onGenerate,
|
||||
onExit: _onExit,
|
||||
),
|
||||
] else ...[
|
||||
AIWriterBlockFooter(
|
||||
onKeep: _onExit,
|
||||
onRewrite: _onRewrite,
|
||||
onDiscard: _onDiscard,
|
||||
),
|
||||
if (prompt.isEmpty && generationCount < 1) ...[
|
||||
_buildInputWidget(context),
|
||||
const Space(0, 10),
|
||||
AIWriterBlockInputField(
|
||||
onGenerate: _onGenerate,
|
||||
onExit: _onExit,
|
||||
),
|
||||
] else ...[
|
||||
AIWriterBlockFooter(
|
||||
onKeep: _onExit,
|
||||
onRewrite: _onRewrite,
|
||||
onDiscard: _onDiscard,
|
||||
),
|
||||
],
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -188,6 +205,12 @@ class _AIWriterBlockComponentState extends State<AIWriterBlockComponent> {
|
||||
}
|
||||
|
||||
Future<void> _onGenerate() async {
|
||||
if (isGenerating) {
|
||||
return;
|
||||
}
|
||||
|
||||
isGenerating = true;
|
||||
|
||||
await aiWriterOperations.updatePromptText(controller.text);
|
||||
|
||||
if (!_isAIWriterEnabled) {
|
||||
@ -219,6 +242,7 @@ class _AIWriterBlockComponentState extends State<AIWriterBlockComponent> {
|
||||
onEnd: () async {
|
||||
barrierDialog?.dismiss();
|
||||
await markdownTextRobot.stop();
|
||||
editorState.service.keyboardService?.enable();
|
||||
},
|
||||
onError: (error) async {
|
||||
barrierDialog?.dismiss();
|
||||
@ -227,6 +251,8 @@ class _AIWriterBlockComponentState extends State<AIWriterBlockComponent> {
|
||||
);
|
||||
|
||||
await aiWriterOperations.updateGenerationCount(generationCount + 1);
|
||||
|
||||
isGenerating = false;
|
||||
}
|
||||
|
||||
Future<void> _onDiscard() async {
|
||||
@ -238,6 +264,12 @@ class _AIWriterBlockComponentState extends State<AIWriterBlockComponent> {
|
||||
}
|
||||
|
||||
Future<void> _onRewrite() async {
|
||||
if (isGenerating) {
|
||||
return;
|
||||
}
|
||||
|
||||
isGenerating = true;
|
||||
|
||||
final previousOutput = _getPreviousOutput();
|
||||
if (previousOutput == null) {
|
||||
return;
|
||||
@ -277,6 +309,8 @@ class _AIWriterBlockComponentState extends State<AIWriterBlockComponent> {
|
||||
);
|
||||
|
||||
await aiWriterOperations.updateGenerationCount(generationCount + 1);
|
||||
|
||||
isGenerating = false;
|
||||
}
|
||||
|
||||
String? _getPreviousOutput() {
|
||||
|
||||
@ -4,6 +4,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/ser
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/error.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/ask_ai_action.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||
import 'package:appflowy/shared/markdown_to_document.dart';
|
||||
import 'package:appflowy/user/application/ai_service.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
@ -141,7 +142,7 @@ class AskAIActionBloc extends Bloc<AskAIEvent, AskAIState> {
|
||||
if (selection == null) {
|
||||
return;
|
||||
}
|
||||
final nodes = markdownToDocument(state.result)
|
||||
final nodes = customMarkdownToDocument(state.result)
|
||||
.root
|
||||
.children
|
||||
.map((e) => e.copyWith())
|
||||
@ -178,7 +179,7 @@ class AskAIActionBloc extends Bloc<AskAIEvent, AskAIState> {
|
||||
return;
|
||||
}
|
||||
|
||||
final nodes = markdownToDocument(state.result)
|
||||
final nodes = customMarkdownToDocument(state.result)
|
||||
.root
|
||||
.children
|
||||
.map((e) => e.copyWith())
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/base/markdown_text_robot.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
@ -236,6 +237,63 @@ void main() {
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
// Partial sample
|
||||
// Sure, let's provide an alternative Rust implementation for the Two Sum problem, focusing on clarity and efficiency but with a slightly different approach:
|
||||
// ```rust
|
||||
// fn two_sum(nums: &[i32], target: i32) -> Vec<(usize, usize)> {
|
||||
// let mut results = Vec::new();
|
||||
// let mut map = std::collections::HashMap::new();
|
||||
//
|
||||
// for (i, &num) in nums.iter().enumerate() {
|
||||
// let complement = target - num;
|
||||
// if let Some(&j) = map.get(&complement) {
|
||||
// results.push((j, i));
|
||||
// }
|
||||
// map.insert(num, i);
|
||||
// }
|
||||
//
|
||||
// results
|
||||
// }
|
||||
//
|
||||
// fn main() {
|
||||
// let nums = vec![2, 7, 11, 15];
|
||||
// let target = 9;
|
||||
//
|
||||
// let pairs = two_sum(&nums, target);
|
||||
// if pairs.is_empty() {
|
||||
// println!("No two sum solution found");
|
||||
// } else {
|
||||
// for (i, j) in pairs {
|
||||
// println!("Indices: {}, {}", i, j);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
test('live refresh (4)', () async {
|
||||
await testLiveRefresh(
|
||||
_liveRefreshSample4,
|
||||
expect: (editorState) {
|
||||
final nodes = editorState.document.root.children;
|
||||
expect(nodes.length, 3);
|
||||
|
||||
final n1 = nodes[0];
|
||||
expect(n1.type, ParagraphBlockKeys.type);
|
||||
expect(
|
||||
n1.delta!.toPlainText(),
|
||||
'''Sure, let's provide an alternative Rust implementation for the Two Sum problem, focusing on clarity and efficiency but with a slightly different approach:''',
|
||||
);
|
||||
|
||||
final n2 = nodes[1];
|
||||
expect(n2.type, CodeBlockKeys.type);
|
||||
expect(
|
||||
n2.delta!.toPlainText(),
|
||||
isNotEmpty,
|
||||
);
|
||||
expect(n2.attributes[CodeBlockKeys.language], 'rust');
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -372,3 +430,153 @@ const _liveRefreshSample3 = [
|
||||
" Enhanced",
|
||||
" survival skills",
|
||||
];
|
||||
|
||||
const _liveRefreshSample4 = [
|
||||
"Sure",
|
||||
", let's",
|
||||
" provide an",
|
||||
" alternative Rust",
|
||||
" implementation for the Two",
|
||||
" Sum",
|
||||
" problem",
|
||||
",",
|
||||
" focusing",
|
||||
" on",
|
||||
" clarity",
|
||||
" and efficiency",
|
||||
" but with",
|
||||
" a slightly",
|
||||
" different approach",
|
||||
":\n\n",
|
||||
"```",
|
||||
"rust",
|
||||
"\nfn two",
|
||||
"_sum",
|
||||
"(nums",
|
||||
": &[",
|
||||
"i",
|
||||
"32",
|
||||
"],",
|
||||
" target",
|
||||
":",
|
||||
" i",
|
||||
"32",
|
||||
")",
|
||||
" ->",
|
||||
" Vec",
|
||||
"<(usize",
|
||||
", usize",
|
||||
")>",
|
||||
" {\n",
|
||||
" ",
|
||||
" let",
|
||||
" mut results",
|
||||
" = Vec::",
|
||||
"new",
|
||||
"();\n",
|
||||
" ",
|
||||
" let mut",
|
||||
" map",
|
||||
" =",
|
||||
" std::collections",
|
||||
"::",
|
||||
"HashMap",
|
||||
"::",
|
||||
"new",
|
||||
"();\n\n ",
|
||||
" for (",
|
||||
"i,",
|
||||
" &num",
|
||||
") in",
|
||||
" nums.iter",
|
||||
"().enumer",
|
||||
"ate()",
|
||||
" {\n let",
|
||||
" complement",
|
||||
" = target",
|
||||
" - num",
|
||||
";\n",
|
||||
" ",
|
||||
" if",
|
||||
" let",
|
||||
" Some(&",
|
||||
"j)",
|
||||
" =",
|
||||
" map",
|
||||
".get(&",
|
||||
"complement",
|
||||
") {\n",
|
||||
" results",
|
||||
".push((",
|
||||
"j",
|
||||
",",
|
||||
" i));\n }\n",
|
||||
" ",
|
||||
" map",
|
||||
".insert",
|
||||
"(num",
|
||||
", i",
|
||||
");\n",
|
||||
" ",
|
||||
" }\n\n ",
|
||||
" results\n",
|
||||
"}\n\n",
|
||||
"fn",
|
||||
" main()",
|
||||
" {\n",
|
||||
" ",
|
||||
" let",
|
||||
" nums",
|
||||
" =",
|
||||
" vec![2, ",
|
||||
"7",
|
||||
",",
|
||||
" 11, 15];\n",
|
||||
" let",
|
||||
" target",
|
||||
" =",
|
||||
" ",
|
||||
"9",
|
||||
";\n\n",
|
||||
" ",
|
||||
" let",
|
||||
" pairs",
|
||||
" = two",
|
||||
"_sum",
|
||||
"(&",
|
||||
"nums",
|
||||
",",
|
||||
" target);\n",
|
||||
" ",
|
||||
" if",
|
||||
" pairs",
|
||||
".is",
|
||||
"_empty()",
|
||||
" {\n ",
|
||||
" println",
|
||||
"!(\"",
|
||||
"No",
|
||||
" two",
|
||||
" sum solution",
|
||||
" found\");\n",
|
||||
" ",
|
||||
" }",
|
||||
" else {\n for",
|
||||
" (",
|
||||
"i",
|
||||
", j",
|
||||
") in",
|
||||
" pairs {\n",
|
||||
" println",
|
||||
"!(\"Indices",
|
||||
":",
|
||||
" {},",
|
||||
" {}\",",
|
||||
" i",
|
||||
",",
|
||||
" j",
|
||||
");\n ",
|
||||
" }\n ",
|
||||
" }\n}\n",
|
||||
"```\n\n",
|
||||
];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user