diff --git a/frontend/appflowy_flutter/integration_test/desktop/cloud/workspace/collaborative_workspace_test.dart b/frontend/appflowy_flutter/integration_test/desktop/cloud/workspace/collaborative_workspace_test.dart index a473e45fb7..4d2e027646 100644 --- a/frontend/appflowy_flutter/integration_test/desktop/cloud/workspace/collaborative_workspace_test.dart +++ b/frontend/appflowy_flutter/integration_test/desktop/cloud/workspace/collaborative_workspace_test.dart @@ -1,7 +1,7 @@ import 'package:appflowy/env/cloud_env.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/loading.dart'; import 'package:appflowy/shared/feature_flags.dart'; +import 'package:appflowy/shared/loading.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_actions.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_menu.dart'; import 'package:easy_localization/easy_localization.dart'; diff --git a/frontend/appflowy_flutter/integration_test/desktop/cloud/workspace/tabs_test.dart b/frontend/appflowy_flutter/integration_test/desktop/cloud/workspace/tabs_test.dart index 6661075878..e79a72d931 100644 --- a/frontend/appflowy_flutter/integration_test/desktop/cloud/workspace/tabs_test.dart +++ b/frontend/appflowy_flutter/integration_test/desktop/cloud/workspace/tabs_test.dart @@ -1,5 +1,5 @@ import 'package:appflowy/env/cloud_env.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/loading.dart'; +import 'package:appflowy/shared/loading.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_menu.dart'; import 'package:appflowy/workspace/presentation/home/tabs/flowy_tab.dart'; import 'package:appflowy/workspace/presentation/home/tabs/tabs_manager.dart'; diff --git a/frontend/appflowy_flutter/integration_test/shared/mock/mock_openai_repository.dart b/frontend/appflowy_flutter/integration_test/shared/mock/mock_openai_repository.dart index 7201bd89ca..062a520f2a 100644 --- a/frontend/appflowy_flutter/integration_test/shared/mock/mock_openai_repository.dart +++ b/frontend/appflowy_flutter/integration_test/shared/mock/mock_openai_repository.dart @@ -1,9 +1,9 @@ import 'dart:async'; import 'dart:convert'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/error.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/openai_client.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/text_completion.dart'; +import 'package:appflowy/ai/error.dart'; +import 'package:appflowy/ai/openai_client.dart'; +import 'package:appflowy/ai/text_completion.dart'; import 'package:http/http.dart' as http; import 'package:mocktail/mocktail.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/ai_client.dart b/frontend/appflowy_flutter/lib/ai/ai_client.dart similarity index 76% rename from frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/ai_client.dart rename to frontend/appflowy_flutter/lib/ai/ai_client.dart index 801f15a77f..0c9ef8b954 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/ai_client.dart +++ b/frontend/appflowy_flutter/lib/ai/ai_client.dart @@ -1,8 +1,9 @@ -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/error.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/text_completion.dart'; -import 'package:appflowy_backend/protobuf/flowy-ai/entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-ai/protobuf.dart'; import 'package:appflowy_result/appflowy_result.dart'; +import 'error.dart'; +import 'text_completion.dart'; + abstract class AIRepository { Future getStreamedCompletions({ required String prompt, diff --git a/frontend/appflowy_flutter/lib/user/application/ai_service.dart b/frontend/appflowy_flutter/lib/ai/appflowy_ai_service.dart similarity index 92% rename from frontend/appflowy_flutter/lib/user/application/ai_service.dart rename to frontend/appflowy_flutter/lib/ai/appflowy_ai_service.dart index e4100cec59..f93a6f8b94 100644 --- a/frontend/appflowy_flutter/lib/user/application/ai_service.dart +++ b/frontend/appflowy_flutter/lib/ai/appflowy_ai_service.dart @@ -3,9 +3,6 @@ import 'dart:ffi'; import 'dart:isolate'; import 'package:appflowy/generated/locale_keys.g.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/ai_client.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/error.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/text_completion.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/ask_ai_action.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-ai/entities.pb.dart'; @@ -13,6 +10,10 @@ import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:fixnum/fixnum.dart' as fixnum; +import 'ai_client.dart'; +import 'error.dart'; +import 'text_completion.dart'; + class AppFlowyAIService implements AIRepository { @override Future, AIError>> generateImage({ diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/error.dart b/frontend/appflowy_flutter/lib/ai/error.dart similarity index 100% rename from frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/error.dart rename to frontend/appflowy_flutter/lib/ai/error.dart diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/openai_client.dart b/frontend/appflowy_flutter/lib/ai/openai_client.dart similarity index 97% rename from frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/openai_client.dart rename to frontend/appflowy_flutter/lib/ai/openai_client.dart index 3b52963125..6f6bc9cc9b 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/openai_client.dart +++ b/frontend/appflowy_flutter/lib/ai/openai_client.dart @@ -1,11 +1,11 @@ import 'dart:async'; import 'dart:convert'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/ai_client.dart'; import 'package:appflowy_backend/protobuf/flowy-ai/entities.pbenum.dart'; import 'package:appflowy_result/appflowy_result.dart'; import 'package:http/http.dart' as http; +import 'ai_client.dart'; import 'error.dart'; import 'text_completion.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/text_completion.dart b/frontend/appflowy_flutter/lib/ai/text_completion.dart similarity index 99% rename from frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/text_completion.dart rename to frontend/appflowy_flutter/lib/ai/text_completion.dart index 067049adbf..4c22325588 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/text_completion.dart +++ b/frontend/appflowy_flutter/lib/ai/text_completion.dart @@ -1,4 +1,5 @@ import 'package:freezed_annotation/freezed_annotation.dart'; + part 'text_completion.freezed.dart'; part 'text_completion.g.dart'; diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_page.dart b/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_page.dart index f90d7ab34a..2d409f58b6 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_page.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_page.dart @@ -2,7 +2,7 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/mobile/presentation/home/mobile_home_page_header.dart'; import 'package:appflowy/mobile/presentation/home/tab/mobile_space_tab.dart'; import 'package:appflowy/mobile/presentation/home/tab/space_order_bloc.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/loading.dart'; +import 'package:appflowy/shared/loading.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy/user/application/reminder/reminder_bloc.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/mobile_media_cell_editor.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/mobile_media_cell_editor.dart index 90e4916fa8..2960a6a34d 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/mobile_media_cell_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/mobile_media_cell_editor.dart @@ -11,6 +11,7 @@ import 'package:appflowy/plugins/database/widgets/media_file_type_ext.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/file/file_util.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/image/common.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/image/multi_image_block_component/image_render.dart'; +import 'package:appflowy/shared/loading.dart'; import 'package:appflowy/workspace/presentation/widgets/image_viewer/interactive_image_viewer.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/file_entities.pbenum.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/media_entities.pb.dart'; @@ -21,8 +22,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; -import '../../../document/presentation/editor_plugins/openai/widgets/loading.dart'; - class MobileMediaCellEditor extends StatelessWidget { const MobileMediaCellEditor({super.key}); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/cover_editor_bloc.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/cover_editor_bloc.dart index 112cfda026..b891aecb6e 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/cover_editor_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/cover_editor_bloc.dart @@ -30,8 +30,7 @@ class ChangeCoverPopoverBloc void _dispatch() { on((event, emit) async { await event.map( - fetchPickedImagePaths: - (FetchPickedImagePaths fetchPickedImagePaths) async { + fetchPickedImagePaths: (fetchPickedImagePaths) async { final imageNames = await _getPreviouslyPickedImagePaths(); emit( @@ -41,11 +40,11 @@ class ChangeCoverPopoverBloc ), ); }, - deleteImage: (DeleteImage deleteImage) async { + deleteImage: (deleteImage) async { final currentState = state; final currentlySelectedImage = node.attributes[DocumentHeaderBlockKeys.coverDetails]; - if (currentState is Loaded) { + if (currentState is _Loaded) { await _deleteImageInStorage(deleteImage.path); if (currentlySelectedImage == deleteImage.path) { _removeCoverImageFromNode(); @@ -54,15 +53,15 @@ class ChangeCoverPopoverBloc .where((path) => path != deleteImage.path) .toList(); _updateImagePathsInStorage(updateImageList); - emit(Loaded(updateImageList)); + emit(ChangeCoverPopoverState.loaded(updateImageList)); } }, - clearAllImages: (ClearAllImages clearAllImages) async { + clearAllImages: (clearAllImages) async { final currentState = state; final currentlySelectedImage = node.attributes[DocumentHeaderBlockKeys.coverDetails]; - if (currentState is Loaded) { + if (currentState is _Loaded) { for (final image in currentState.imageNames) { await _deleteImageInStorage(image); if (currentlySelectedImage == image) { @@ -70,7 +69,7 @@ class ChangeCoverPopoverBloc } } _updateImagePathsInStorage([]); - emit(const Loaded([])); + emit(const ChangeCoverPopoverState.loaded([])); } }, ); @@ -113,18 +112,18 @@ class ChangeCoverPopoverBloc class ChangeCoverPopoverEvent with _$ChangeCoverPopoverEvent { const factory ChangeCoverPopoverEvent.fetchPickedImagePaths({ @Default(false) bool selectLatestImage, - }) = FetchPickedImagePaths; + }) = _FetchPickedImagePaths; - const factory ChangeCoverPopoverEvent.deleteImage(String path) = DeleteImage; - const factory ChangeCoverPopoverEvent.clearAllImages() = ClearAllImages; + const factory ChangeCoverPopoverEvent.deleteImage(String path) = _DeleteImage; + const factory ChangeCoverPopoverEvent.clearAllImages() = _ClearAllImages; } @freezed class ChangeCoverPopoverState with _$ChangeCoverPopoverState { - const factory ChangeCoverPopoverState.initial() = Initial; - const factory ChangeCoverPopoverState.loading() = Loading; + const factory ChangeCoverPopoverState.initial() = _Initial; + const factory ChangeCoverPopoverState.loading() = _Loading; const factory ChangeCoverPopoverState.loaded( List imageNames, { @Default(false) selectLatestImage, - }) = Loaded; + }) = _Loaded; } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker.dart index 3f84d04283..f5df4c0904 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker.dart @@ -36,43 +36,49 @@ class _CoverImagePickerState extends State { ..add(const CoverImagePickerEvent.initialEvent()), child: BlocListener( listener: (context, state) { - if (state is NetworkImagePicked) { - state.successOrFail.fold( - (s) {}, - (e) => showSnapBar( - context, - LocaleKeys.document_plugins_cover_invalidImageUrl.tr(), - ), - ); - } - if (state is Done) { - state.successOrFail.fold( - (l) => widget.onFileSubmit(l), - (r) => showSnapBar( - context, - LocaleKeys.document_plugins_cover_failedToAddImageToGallery - .tr(), - ), - ); - } + state.maybeWhen( + networkImage: (successOrFail) { + successOrFail.fold( + (s) {}, + (e) => showSnapBar( + context, + LocaleKeys.document_plugins_cover_invalidImageUrl.tr(), + ), + ); + }, + done: (successOrFail) { + successOrFail.fold( + (l) => widget.onFileSubmit(l), + (r) => showSnapBar( + context, + LocaleKeys.document_plugins_cover_failedToAddImageToGallery + .tr(), + ), + ); + }, + orElse: () {}, + ); }, child: BlocBuilder( builder: (context, state) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - state is Loading - ? const SizedBox( - height: 180, - child: Center( - child: CircularProgressIndicator(), - ), - ) - : CoverImagePreviewWidget(state: state), + state.maybeMap( + loading: (_) => const SizedBox( + height: 180, + child: Center( + child: CircularProgressIndicator(), + ), + ), + orElse: () => CoverImagePreviewWidget(state: state), + ), const VSpace(10), NetworkImageUrlInput( onAdd: (url) { - context.read().add(UrlSubmit(url)); + context + .read() + .add(CoverImagePickerEvent.urlSubmit(url)); }, ), const VSpace(10), @@ -81,9 +87,9 @@ class _CoverImagePickerState extends State { widget.onBackPressed(); }, onSave: () { - context.read().add( - SaveToGallery(state), - ); + context + .read() + .add(CoverImagePickerEvent.saveToGallery(state)); }, ), ], @@ -196,7 +202,7 @@ class ImagePickerActionButtons extends StatelessWidget { class CoverImagePreviewWidget extends StatefulWidget { const CoverImagePreviewWidget({super.key, required this.state}); - final dynamic state; + final CoverImagePickerState state; @override State createState() => @@ -242,7 +248,9 @@ class _CoverImagePreviewWidgetState extends State { FlowyButton( hoverColor: Theme.of(context).hoverColor, onTap: () { - ctx.read().add(const PickFileImage()); + ctx + .read() + .add(const CoverImagePickerEvent.pickFileImage()); }, useIntrinsicWidth: true, leftIcon: const FlowySvg( @@ -265,7 +273,9 @@ class _CoverImagePreviewWidgetState extends State { top: 10, child: InkWell( onTap: () { - ctx.read().add(const DeleteImage()); + ctx + .read() + .add(const CoverImagePickerEvent.deleteImage()); }, child: DecoratedBox( decoration: BoxDecoration( @@ -291,42 +301,42 @@ class _CoverImagePreviewWidgetState extends State { decoration: BoxDecoration( color: Theme.of(context).colorScheme.secondary, borderRadius: Corners.s6Border, - image: widget.state is Initial - ? null - : widget.state is NetworkImagePicked - ? widget.state.successOrFail.fold( - (path) => DecorationImage( - image: NetworkImage(path), - fit: BoxFit.cover, - ), - (r) => null, - ) - : widget.state is FileImagePicked - ? DecorationImage( - image: FileImage(File(widget.state.path)), - fit: BoxFit.cover, - ) - : null, + image: widget.state.whenOrNull( + networkImage: (successOrFail) { + return successOrFail.fold( + (path) => DecorationImage( + image: NetworkImage(path), + fit: BoxFit.cover, + ), + (r) => null, + ); + }, + fileImage: (path) { + return DecorationImage( + image: FileImage(File(path)), + fit: BoxFit.cover, + ); + }, + ), + ), + child: widget.state.whenOrNull( + initial: () => _buildFilePickerWidget(context), + networkImage: (successOrFail) => successOrFail.fold( + (l) => null, + (r) => _buildFilePickerWidget( + context, + ), + ), ), - child: (widget.state is Initial) - ? _buildFilePickerWidget(context) - : (widget.state is NetworkImagePicked) - ? widget.state.successOrFail.fold( - (l) => null, - (r) => _buildFilePickerWidget( - context, - ), - ) - : null, ), - (widget.state is FileImagePicked) - ? _buildImageDeleteButton(context) - : (widget.state is NetworkImagePicked) - ? widget.state.successOrFail.fold( - (l) => _buildImageDeleteButton(context), - (r) => const SizedBox.shrink(), - ) - : const SizedBox.shrink(), + widget.state.maybeWhen( + fileImage: (_) => _buildImageDeleteButton(context), + networkImage: (successOrFail) => successOrFail.fold( + (l) => _buildImageDeleteButton(context), + (r) => const SizedBox.shrink(), + ), + orElse: () => const SizedBox.shrink(), + ), ], ); } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker_bloc.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker_bloc.dart index 9ead1ff3f4..64e21eb773 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker_bloc.dart @@ -28,10 +28,10 @@ class CoverImagePickerBloc on( (event, emit) async { await event.map( - initialEvent: (InitialEvent initialEvent) { + initialEvent: (initialEvent) { emit(const CoverImagePickerState.initial()); }, - urlSubmit: (UrlSubmit urlSubmit) async { + urlSubmit: (urlSubmit) async { emit(const CoverImagePickerState.loading()); final validateImage = await _validateURL(urlSubmit.path); if (validateImage) { @@ -53,7 +53,7 @@ class CoverImagePickerBloc ); } }, - pickFileImage: (PickFileImage pickFileImage) async { + pickFileImage: (pickFileImage) async { final imagePickerResults = await _pickImages(); if (imagePickerResults != null) { emit(CoverImagePickerState.fileImage(imagePickerResults)); @@ -61,10 +61,10 @@ class CoverImagePickerBloc emit(const CoverImagePickerState.initial()); } }, - deleteImage: (DeleteImage deleteImage) { + deleteImage: (deleteImage) { emit(const CoverImagePickerState.initial()); }, - saveToGallery: (SaveToGallery saveToGallery) async { + saveToGallery: (saveToGallery) async { emit(const CoverImagePickerState.loading()); final saveImage = await _saveToGallery(saveToGallery.previousState); if (saveImage != null) { @@ -93,7 +93,7 @@ class CoverImagePickerBloc final List imagePaths = prefs.getStringList(kLocalImagesKey) ?? []; final directory = await _coverPath(); - if (state is FileImagePicked) { + if (state is _FileImagePicked) { try { final path = state.path; final newPath = p.join(directory, p.split(path).last); @@ -102,7 +102,7 @@ class CoverImagePickerBloc } catch (e) { return null; } - } else if (state is NetworkImagePicked) { + } else if (state is _NetworkImagePicked) { try { final url = state.successOrFail.fold((path) => path, (r) => null); if (url != null) { @@ -197,25 +197,25 @@ class CoverImagePickerBloc @freezed class CoverImagePickerEvent with _$CoverImagePickerEvent { - const factory CoverImagePickerEvent.urlSubmit(String path) = UrlSubmit; - const factory CoverImagePickerEvent.pickFileImage() = PickFileImage; - const factory CoverImagePickerEvent.deleteImage() = DeleteImage; + const factory CoverImagePickerEvent.urlSubmit(String path) = _UrlSubmit; + const factory CoverImagePickerEvent.pickFileImage() = _PickFileImage; + const factory CoverImagePickerEvent.deleteImage() = _DeleteImage; const factory CoverImagePickerEvent.saveToGallery( CoverImagePickerState previousState, - ) = SaveToGallery; - const factory CoverImagePickerEvent.initialEvent() = InitialEvent; + ) = _SaveToGallery; + const factory CoverImagePickerEvent.initialEvent() = _InitialEvent; } @freezed class CoverImagePickerState with _$CoverImagePickerState { - const factory CoverImagePickerState.initial() = Initial; - const factory CoverImagePickerState.loading() = Loading; + const factory CoverImagePickerState.initial() = _Initial; + const factory CoverImagePickerState.loading() = _Loading; const factory CoverImagePickerState.networkImage( FlowyResult successOrFail, - ) = NetworkImagePicked; - const factory CoverImagePickerState.fileImage(String path) = FileImagePicked; + ) = _NetworkImagePicked; + const factory CoverImagePickerState.fileImage(String path) = _FileImagePicked; const factory CoverImagePickerState.done( FlowyResult, FlowyError> successOrFail, - ) = Done; + ) = _Done; } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/text_edit.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/text_edit.dart deleted file mode 100644 index 52cce9da4f..0000000000 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/text_edit.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:freezed_annotation/freezed_annotation.dart'; -part 'text_edit.freezed.dart'; -part 'text_edit.g.dart'; - -@freezed -class TextEditChoice with _$TextEditChoice { - factory TextEditChoice({ - required String text, - required int index, - }) = _TextEditChoice; - - factory TextEditChoice.fromJson(Map json) => - _$TextEditChoiceFromJson(json); -} - -@freezed -class TextEditResponse with _$TextEditResponse { - const factory TextEditResponse({ - required List choices, - }) = _TextEditResponse; - - factory TextEditResponse.fromJson(Map json) => - _$TextEditResponseFromJson(json); -} diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/ai_writer_block_component.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/ai_writer_block_component.dart index 2938e87516..24196aa439 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/ai_writer_block_component.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/ai_writer_block_component.dart @@ -1,13 +1,9 @@ +import 'package:appflowy/ai/appflowy_ai_service.dart'; +import 'package:appflowy/ai/error.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/application/prelude.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/base/build_context_extension.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/base/markdown_text_robot.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/error.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/ai_writer_block_operations.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/ai_writer_block_widgets.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/discard_dialog.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/loading.dart'; -import 'package:appflowy/user/application/ai_service.dart'; import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-ai/entities.pb.dart'; @@ -20,6 +16,10 @@ import 'package:provider/provider.dart'; import 'package:universal_platform/universal_platform.dart'; import 'ai_limit_dialog.dart'; +import 'ai_writer_block_operations.dart'; +import 'ai_writer_block_widgets.dart'; +import 'discard_dialog.dart'; +import 'barrier_dialog.dart'; class AIWriterBlockKeys { const AIWriterBlockKeys._(); @@ -91,8 +91,7 @@ class _AIWriterBlockComponentState extends State { late final editorState = context.read(); late final SelectionGestureInterceptor interceptor; - late final AIWriterBlockOperations aiWriterOperations = - AIWriterBlockOperations( + late final aiWriterOperations = AIWriterBlockOperations( editorState: editorState, aiWriterNode: widget.node, ); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/ask_ai_action_bloc.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/ask_ai_action_bloc.dart index 82cd627180..b464c72d1a 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/ask_ai_action_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/ask_ai_action_bloc.dart @@ -1,11 +1,11 @@ import 'dart:async'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/ai_client.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/error.dart'; +import 'package:appflowy/ai/ai_client.dart'; +import 'package:appflowy/ai/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/ai/appflowy_ai_service.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/ask_ai_block_component.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/ask_ai_block_component.dart index 7babb48ba5..214a5affba 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/ask_ai_block_component.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/ask_ai_block_component.dart @@ -1,8 +1,8 @@ import 'dart:async'; import 'package:appflowy/generated/locale_keys.g.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/ai_client.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/error.dart'; +import 'package:appflowy/ai/ai_client.dart'; +import 'package:appflowy/ai/error.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/ai_limit_dialog.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/ask_ai_action.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/ask_ai_action_bloc.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/barrier_dialog.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/barrier_dialog.dart new file mode 100644 index 0000000000..4b0df658ac --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/barrier_dialog.dart @@ -0,0 +1,24 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; + +class BarrierDialog { + BarrierDialog(this.context); + + late BuildContext loadingContext; + final BuildContext context; + + void show() => unawaited( + showDialog( + context: context, + barrierDismissible: false, + barrierColor: Colors.transparent, + builder: (BuildContext context) { + loadingContext = context; + return const SizedBox.shrink(); + }, + ), + ); + + void dismiss() => Navigator.of(loadingContext).pop(); +} diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/loading.dart b/frontend/appflowy_flutter/lib/shared/loading.dart similarity index 69% rename from frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/loading.dart rename to frontend/appflowy_flutter/lib/shared/loading.dart index 6f475bc627..f8d1c6fc86 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/loading.dart +++ b/frontend/appflowy_flutter/lib/shared/loading.dart @@ -47,24 +47,3 @@ class Loading { hasStopped = true; } } - -class BarrierDialog { - BarrierDialog(this.context); - - late BuildContext loadingContext; - final BuildContext context; - - void show() => unawaited( - showDialog( - context: context, - barrierDismissible: false, - barrierColor: Colors.transparent, - builder: (BuildContext context) { - loadingContext = context; - return const SizedBox.shrink(); - }, - ), - ); - - void dismiss() => Navigator.of(loadingContext).pop(); -} diff --git a/frontend/appflowy_flutter/lib/startup/deps_resolver.dart b/frontend/appflowy_flutter/lib/startup/deps_resolver.dart index 71f8935ee2..df5b3c1473 100644 --- a/frontend/appflowy_flutter/lib/startup/deps_resolver.dart +++ b/frontend/appflowy_flutter/lib/startup/deps_resolver.dart @@ -3,13 +3,13 @@ import 'package:appflowy/core/network_monitor.dart'; import 'package:appflowy/env/cloud_env.dart'; import 'package:appflowy/plugins/document/application/prelude.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/clipboard_service.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/ai_client.dart'; +import 'package:appflowy/ai/ai_client.dart'; import 'package:appflowy/plugins/trash/application/prelude.dart'; import 'package:appflowy/shared/appflowy_cache_manager.dart'; import 'package:appflowy/shared/custom_image_cache_manager.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/startup/tasks/appflowy_cloud_task.dart'; -import 'package:appflowy/user/application/ai_service.dart'; +import 'package:appflowy/ai/appflowy_ai_service.dart'; import 'package:appflowy/user/application/auth/af_cloud_auth_service.dart'; import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy/user/application/prelude.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar.dart index 1a396b26dd..f9af95ad73 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar.dart @@ -4,8 +4,8 @@ import 'dart:io'; import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/blank/blank.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/loading.dart'; import 'package:appflowy/shared/feature_flags.dart'; +import 'package:appflowy/shared/loading.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/workspace/application/action_navigation/action_navigation_bloc.dart'; import 'package:appflowy/workspace/application/action_navigation/navigation_action.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/workspace/sidebar_workspace.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/workspace/sidebar_workspace.dart index aee527d1a8..038ec9f5a6 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/workspace/sidebar_workspace.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/workspace/sidebar_workspace.dart @@ -1,6 +1,6 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/loading.dart'; +import 'package:appflowy/shared/loading.dart'; import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/shared/sidebar_setting.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_icon.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/account_deletion.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/account_deletion.dart index 368cd19138..6f1c4920cb 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/account_deletion.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/account/account_deletion.dart @@ -1,6 +1,6 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/loading.dart'; +import 'package:appflowy/shared/loading.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/user/application/user_service.dart'; import 'package:appflowy/util/navigator_context_extension.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_billing_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_billing_view.dart index 0c57c9e158..450f2167de 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_billing_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_billing_view.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:appflowy/shared/flowy_error_page.dart'; +import 'package:appflowy/shared/loading.dart'; import 'package:appflowy/util/int64_extension.dart'; import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart'; import 'package:appflowy/workspace/application/settings/billing/settings_billing_bloc.dart'; @@ -25,7 +26,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../generated/locale_keys.g.dart'; -import '../../../../plugins/document/presentation/editor_plugins/openai/widgets/loading.dart'; const _buttonsMinWidth = 100.0; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_comparison_dialog.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_comparison_dialog.dart index d9103b4cd4..05e7d87b6b 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_comparison_dialog.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_comparison_dialog.dart @@ -1,4 +1,5 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/shared/loading.dart'; import 'package:appflowy/util/theme_extension.dart'; import 'package:appflowy/workspace/application/settings/plan/settings_plan_bloc.dart'; import 'package:appflowy/workspace/application/settings/plan/workspace_subscription_ext.dart'; @@ -13,7 +14,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../generated/locale_keys.g.dart'; -import '../../../../plugins/document/presentation/editor_plugins/openai/widgets/loading.dart'; class SettingsPlanComparisonDialog extends StatefulWidget { const SettingsPlanComparisonDialog({ diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_view.dart index 61cb83d1ae..2230650164 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_view.dart @@ -4,6 +4,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/shared/colors.dart'; import 'package:appflowy/shared/flowy_error_page.dart'; +import 'package:appflowy/shared/loading.dart'; import 'package:appflowy/util/int64_extension.dart'; import 'package:appflowy/util/theme_extension.dart'; import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart'; @@ -24,8 +25,6 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import '../../../../plugins/document/presentation/editor_plugins/openai/widgets/loading.dart'; - class SettingsPlanView extends StatefulWidget { const SettingsPlanView({ super.key, diff --git a/frontend/appflowy_flutter/test/bloc_test/ask_ai_test/ask_ai_action_bloc_test.dart b/frontend/appflowy_flutter/test/bloc_test/ask_ai_test/ask_ai_action_bloc_test.dart index 8c6f798656..3165f541ea 100644 --- a/frontend/appflowy_flutter/test/bloc_test/ask_ai_test/ask_ai_action_bloc_test.dart +++ b/frontend/appflowy_flutter/test/bloc_test/ask_ai_test/ask_ai_action_bloc_test.dart @@ -1,5 +1,5 @@ -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/ai_client.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/error.dart'; +import 'package:appflowy/ai/ai_client.dart'; +import 'package:appflowy/ai/error.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/ask_ai_action.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/ask_ai_action_bloc.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';