mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Fix/1936 (#1939)
* fix: [Bug] Code block jump skip blank line
* fix: auto completion interaction
* Revert "fix: [Bug] Code block jump skip blank line"
This reverts commit 5a252bcb18
.
* fix: [Bug] Code block jump skip blank line
* fix: number list parse error
This commit is contained in:
@ -2,7 +2,6 @@ import 'dart:convert';
|
|||||||
|
|
||||||
import 'package:appflowy/plugins/document/presentation/plugins/openai/service/text_edit.dart';
|
import 'package:appflowy/plugins/document/presentation/plugins/openai/service/text_edit.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'text_completion.dart';
|
import 'text_completion.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
@ -39,7 +38,7 @@ abstract class OpenAIRepository {
|
|||||||
Future<Either<OpenAIError, TextCompletionResponse>> getCompletions({
|
Future<Either<OpenAIError, TextCompletionResponse>> getCompletions({
|
||||||
required String prompt,
|
required String prompt,
|
||||||
String? suffix,
|
String? suffix,
|
||||||
int maxTokens = 500,
|
int maxTokens = 2048,
|
||||||
double temperature = .3,
|
double temperature = .3,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -47,10 +46,10 @@ abstract class OpenAIRepository {
|
|||||||
required String prompt,
|
required String prompt,
|
||||||
required Future<void> Function() onStart,
|
required Future<void> Function() onStart,
|
||||||
required Future<void> Function(TextCompletionResponse response) onProcess,
|
required Future<void> Function(TextCompletionResponse response) onProcess,
|
||||||
required VoidCallback onEnd,
|
required Future<void> Function() onEnd,
|
||||||
required void Function(OpenAIError error) onError,
|
required void Function(OpenAIError error) onError,
|
||||||
String? suffix,
|
String? suffix,
|
||||||
int maxTokens = 500,
|
int maxTokens = 2048,
|
||||||
double temperature = 0.3,
|
double temperature = 0.3,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -85,7 +84,7 @@ class HttpOpenAIRepository implements OpenAIRepository {
|
|||||||
Future<Either<OpenAIError, TextCompletionResponse>> getCompletions({
|
Future<Either<OpenAIError, TextCompletionResponse>> getCompletions({
|
||||||
required String prompt,
|
required String prompt,
|
||||||
String? suffix,
|
String? suffix,
|
||||||
int maxTokens = 500,
|
int maxTokens = 2048,
|
||||||
double temperature = 0.3,
|
double temperature = 0.3,
|
||||||
}) async {
|
}) async {
|
||||||
final parameters = {
|
final parameters = {
|
||||||
@ -121,10 +120,10 @@ class HttpOpenAIRepository implements OpenAIRepository {
|
|||||||
required String prompt,
|
required String prompt,
|
||||||
required Future<void> Function() onStart,
|
required Future<void> Function() onStart,
|
||||||
required Future<void> Function(TextCompletionResponse response) onProcess,
|
required Future<void> Function(TextCompletionResponse response) onProcess,
|
||||||
required VoidCallback onEnd,
|
required Future<void> Function() onEnd,
|
||||||
required void Function(OpenAIError error) onError,
|
required void Function(OpenAIError error) onError,
|
||||||
String? suffix,
|
String? suffix,
|
||||||
int maxTokens = 500,
|
int maxTokens = 2048,
|
||||||
double temperature = 0.3,
|
double temperature = 0.3,
|
||||||
}) async {
|
}) async {
|
||||||
final parameters = {
|
final parameters = {
|
||||||
@ -159,21 +158,23 @@ class HttpOpenAIRepository implements OpenAIRepository {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final data = chunk.trim().split('data: ');
|
final data = chunk.trim().split('data: ');
|
||||||
if (data.length > 1 && data[1] != '[DONE]') {
|
Log.editor.info(data.toString());
|
||||||
final response = TextCompletionResponse.fromJson(
|
if (data.length > 1) {
|
||||||
json.decode(data[1]),
|
if (data[1] != '[DONE]') {
|
||||||
);
|
final response = TextCompletionResponse.fromJson(
|
||||||
if (response.choices.isNotEmpty) {
|
json.decode(data[1]),
|
||||||
final text = response.choices.first.text;
|
);
|
||||||
if (text == previousSyntax && text == '\n') {
|
if (response.choices.isNotEmpty) {
|
||||||
continue;
|
final text = response.choices.first.text;
|
||||||
|
if (text == previousSyntax && text == '\n') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
await onProcess(response);
|
||||||
|
previousSyntax = response.choices.first.text;
|
||||||
}
|
}
|
||||||
await onProcess(response);
|
} else {
|
||||||
previousSyntax = response.choices.first.text;
|
onEnd();
|
||||||
Log.editor.info(response.choices.first.text);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
onEnd();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -69,6 +69,8 @@ class _AutoCompletionInputState extends State<_AutoCompletionInput> {
|
|||||||
void dispose() {
|
void dispose() {
|
||||||
controller.dispose();
|
controller.dispose();
|
||||||
textFieldFocusNode.removeListener(_onFocusChanged);
|
textFieldFocusNode.removeListener(_onFocusChanged);
|
||||||
|
widget.editorState.service.selectionService.currentSelection
|
||||||
|
.removeListener(_onCancelWhenSelectionChanged);
|
||||||
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
@ -239,6 +241,7 @@ class _AutoCompletionInputState extends State<_AutoCompletionInput> {
|
|||||||
final result = await UserBackendService.getCurrentUserProfile();
|
final result = await UserBackendService.getCurrentUserProfile();
|
||||||
|
|
||||||
result.fold((userProfile) async {
|
result.fold((userProfile) async {
|
||||||
|
BarrierDialog? barrierDialog;
|
||||||
final openAIRepository = HttpOpenAIRepository(
|
final openAIRepository = HttpOpenAIRepository(
|
||||||
client: http.Client(),
|
client: http.Client(),
|
||||||
apiKey: userProfile.openaiKey,
|
apiKey: userProfile.openaiKey,
|
||||||
@ -247,6 +250,8 @@ class _AutoCompletionInputState extends State<_AutoCompletionInput> {
|
|||||||
prompt: controller.text,
|
prompt: controller.text,
|
||||||
onStart: () async {
|
onStart: () async {
|
||||||
loading.stop();
|
loading.stop();
|
||||||
|
barrierDialog = BarrierDialog(context);
|
||||||
|
barrierDialog?.show();
|
||||||
await _makeSurePreviousNodeIsEmptyTextNode();
|
await _makeSurePreviousNodeIsEmptyTextNode();
|
||||||
},
|
},
|
||||||
onProcess: (response) async {
|
onProcess: (response) async {
|
||||||
@ -255,10 +260,15 @@ class _AutoCompletionInputState extends State<_AutoCompletionInput> {
|
|||||||
await widget.editorState.autoInsertText(
|
await widget.editorState.autoInsertText(
|
||||||
text,
|
text,
|
||||||
inputType: TextRobotInputType.word,
|
inputType: TextRobotInputType.word,
|
||||||
|
delay: Duration.zero,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onEnd: () {},
|
onEnd: () async {
|
||||||
|
await barrierDialog?.dismiss();
|
||||||
|
widget.editorState.service.selectionService.currentSelection
|
||||||
|
.addListener(_onCancelWhenSelectionChanged);
|
||||||
|
},
|
||||||
onError: (error) async {
|
onError: (error) async {
|
||||||
loading.stop();
|
loading.stop();
|
||||||
await _showError(error.message);
|
await _showError(error.message);
|
||||||
@ -353,4 +363,6 @@ class _AutoCompletionInputState extends State<_AutoCompletionInput> {
|
|||||||
widget.editorState.service.keyboardService?.enable();
|
widget.editorState.service.keyboardService?.enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onCancelWhenSelectionChanged() {}
|
||||||
}
|
}
|
||||||
|
@ -32,3 +32,28 @@ class Loading {
|
|||||||
return Navigator.of(loadingContext).pop();
|
return Navigator.of(loadingContext).pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class BarrierDialog {
|
||||||
|
BarrierDialog(
|
||||||
|
this.context,
|
||||||
|
);
|
||||||
|
|
||||||
|
late BuildContext loadingContext;
|
||||||
|
final BuildContext context;
|
||||||
|
|
||||||
|
Future<void> show() async {
|
||||||
|
return showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
barrierColor: Colors.transparent,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
loadingContext = context;
|
||||||
|
return Container();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> dismiss() async {
|
||||||
|
return Navigator.of(loadingContext).pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -38,10 +38,10 @@ EXTERNAL SOURCES:
|
|||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
flowy_infra_ui: c34d49d615ed9fe552cd47f90d7850815a74e9e9
|
flowy_infra_ui: c34d49d615ed9fe552cd47f90d7850815a74e9e9
|
||||||
FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811
|
FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811
|
||||||
path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852
|
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
|
||||||
rich_clipboard_macos: 43364b66b9dc69d203eb8dd6d758e2d12e02723c
|
rich_clipboard_macos: 43364b66b9dc69d203eb8dd6d758e2d12e02723c
|
||||||
shared_preferences_foundation: 297b3ebca31b34ec92be11acd7fb0ba932c822ca
|
shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472
|
||||||
url_launcher_macos: c04e4fa86382d4f94f6b38f14625708be3ae52e2
|
url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451
|
||||||
|
|
||||||
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
||||||
|
|
||||||
|
@ -95,11 +95,18 @@ class _FlowyRichTextState extends State<FlowyRichText> with SelectableMixin {
|
|||||||
textPosition, Rect.zero) ??
|
textPosition, Rect.zero) ??
|
||||||
Offset.zero;
|
Offset.zero;
|
||||||
}
|
}
|
||||||
|
if (widget.cursorHeight != null && cursorHeight != null) {
|
||||||
|
cursorOffset = Offset(
|
||||||
|
cursorOffset.dx,
|
||||||
|
cursorOffset.dy + (cursorHeight - widget.cursorHeight!) / 2,
|
||||||
|
);
|
||||||
|
cursorHeight = widget.cursorHeight;
|
||||||
|
}
|
||||||
final rect = Rect.fromLTWH(
|
final rect = Rect.fromLTWH(
|
||||||
cursorOffset.dx - (widget.cursorWidth / 2.0),
|
cursorOffset.dx - (widget.cursorWidth / 2.0),
|
||||||
cursorOffset.dy,
|
cursorOffset.dy,
|
||||||
widget.cursorWidth,
|
widget.cursorWidth,
|
||||||
widget.cursorHeight ?? cursorHeight ?? 16.0,
|
cursorHeight ?? 16.0,
|
||||||
);
|
);
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,9 @@ ShortcutEventHandler whiteSpaceHandler = (editorState, event) {
|
|||||||
} else if (numberMatch != null) {
|
} else if (numberMatch != null) {
|
||||||
final matchText = numberMatch.group(0);
|
final matchText = numberMatch.group(0);
|
||||||
final numText = numberMatch.group(1);
|
final numText = numberMatch.group(1);
|
||||||
if (matchText != null && numText != null) {
|
if (matchText != null &&
|
||||||
|
numText != null &&
|
||||||
|
matchText.length == selection.startIndex) {
|
||||||
return _toNumberList(editorState, textNode, matchText, numText);
|
return _toNumberList(editorState, textNode, matchText, numText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,8 @@ class __CodeBlockNodeWidgeState extends State<_CodeBlockNodeWidge>
|
|||||||
key: _richTextKey,
|
key: _richTextKey,
|
||||||
textNode: widget.textNode,
|
textNode: widget.textNode,
|
||||||
editorState: widget.editorState,
|
editorState: widget.editorState,
|
||||||
|
lineHeight: 1.0,
|
||||||
|
cursorHeight: 15.0,
|
||||||
textSpanDecorator: (textSpan) => TextSpan(
|
textSpanDecorator: (textSpan) => TextSpan(
|
||||||
style: widget.editorState.editorStyle.textStyle,
|
style: widget.editorState.editorStyle.textStyle,
|
||||||
children: codeTextSpan,
|
children: codeTextSpan,
|
||||||
|
Reference in New Issue
Block a user