Use bindings to better separate scribe presentation and data layer

This commit is contained in:
Théo Poizat
2025-12-08 15:03:33 +01:00
committed by Dat H. Pham
parent 6dc58e2eb6
commit bb23792fe3
7 changed files with 61 additions and 10 deletions
@@ -74,6 +74,7 @@ import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart';
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
import 'package:tmail_ui_user/main/utils/ios_sharing_manager.dart';
import 'package:uuid/uuid.dart';
import 'package:scribe/scribe/ai/domain/usecases/generate_ai_text_interactor.dart';
class ComposerBindings extends BaseBindings {
@@ -338,6 +339,7 @@ class ComposerBindings extends BaseBindings {
Get.find<PrintEmailInteractor>(tag: composerId),
Get.find<ComposerRepository>(tag: composerId),
Get.find<SaveTemplateEmailInteractor>(tag: composerId),
Get.find<GenerateAITextInteractor>(),
composerId: composerId,
composerArgs: composerArguments,
), tag: composerId);
@@ -180,6 +180,7 @@ class ComposerController extends BaseController
final String? composerId;
final ComposerArguments? composerArgs;
final SaveTemplateEmailInteractor _saveTemplateEmailInteractor;
final GenerateAITextInteractor _generateAITextInteractor;
GetAllAutoCompleteInteractor? _getAllAutoCompleteInteractor;
GetAutoCompleteInteractor? _getAutoCompleteInteractor;
@@ -287,6 +288,7 @@ class ComposerController extends BaseController
this.printEmailInteractor,
this._composerRepository,
this._saveTemplateEmailInteractor,
this._generateAITextInteractor,
{
this.composerId,
this.composerArgs,
@@ -920,6 +922,7 @@ class ComposerController extends BaseController
imagePaths: imagePaths,
content: fullText,
onInsertText: insertTextInEditor,
interactor: _generateAITextInteractor,
buttonPosition: buttonPosition,
);
}
@@ -935,6 +938,7 @@ class ComposerController extends BaseController
imagePaths: imagePaths,
content: selection,
onInsertText: insertTextInEditor,
interactor: _generateAITextInteractor,
buttonPosition: buttonPosition,
);
}
@@ -0,0 +1,44 @@
import 'package:dio/dio.dart';
import 'package:get/get.dart';
import 'package:scribe/scribe/ai/data/datasource/ai_datasource.dart';
import 'package:scribe/scribe/ai/data/datasource_impl/ai_datasource_impl.dart';
import 'package:scribe/scribe/ai/data/repository/ai_repository_impl.dart';
import 'package:scribe/scribe/ai/domain/repository/ai_scribe_repository.dart';
import 'package:scribe/scribe/ai/domain/usecases/generate_ai_text_interactor.dart';
class AIScribeBindings extends Bindings {
@override
void dependencies() {
_bindingsDataSourceImpl();
_bindingsDataSource();
_bindingsRepositoryImpl();
_bindingsRepository();
_bindingsInteractor();
}
void _bindingsDataSourceImpl() {
Get.lazyPut<AIDataSourceImpl>(() => AIDataSourceImpl(
dio: Dio(), // Dedicated Dio instance without authorization interceptors
));
}
void _bindingsDataSource() {
Get.lazyPut<AIDataSource>(() => Get.find<AIDataSourceImpl>());
}
void _bindingsRepositoryImpl() {
Get.lazyPut<AIScribeRepositoryImpl>(() => AIScribeRepositoryImpl(
Get.find<AIDataSource>(),
));
}
void _bindingsRepository() {
Get.lazyPut<AIScribeRepository>(() => Get.find<AIScribeRepositoryImpl>());
}
void _bindingsInteractor() {
Get.lazyPut<GenerateAITextInteractor>(() => GenerateAITextInteractor(
Get.find<AIScribeRepository>(),
));
}
}
@@ -1,10 +1,7 @@
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/utils/app_logger.dart';
import 'package:scribe/scribe/ai/data/datasource_impl/ai_datasource_impl.dart';
import 'package:scribe/scribe/ai/data/repository/ai_repository_impl.dart';
import 'package:scribe/scribe/ai/domain/state/generate_ai_text_state.dart';
import 'package:scribe/scribe/ai/domain/usecases/generate_ai_text_interactor.dart';
import 'package:scribe/scribe/ai/presentation/model/ai_action.dart';
@@ -21,6 +18,7 @@ Future<void> showAIScribeDialog({
required ImagePaths imagePaths,
required String content,
required AIScribeResultCallback onInsertText,
required GenerateAITextInteractor interactor,
List<AIScribeMenuCategory>? availableCategories,
Offset? buttonPosition,
}) async {
@@ -109,7 +107,7 @@ Future<void> showAIScribeDialog({
context: context,
barrierDismissible: true,
builder: (context) {
final suggestionFuture = _executeAIRequest(selectedAction, content);
final suggestionFuture = _executeAIRequest(interactor, selectedAction, content);
final title = selectedAction.getLabel(context);
final modalContent = AIScribeSuggestion(
@@ -194,14 +192,10 @@ Future<void> showAIScribeDialog({
}
Future<String> _executeAIRequest(
GenerateAITextInteractor interactor,
AIAction action,
String content,
) async {
final dio = Dio();
final dataSource = AIDataSourceImpl(dio: dio);
final repository = AIScribeRepositoryImpl(dataSource);
final interactor = GenerateAITextInteractor(repository);
final result = await interactor.execute(action, content);
return result.fold(
+1 -1
View File
@@ -581,7 +581,7 @@ packages:
source: hosted
version: "4.0.0"
get:
dependency: transitive
dependency: "direct main"
description:
name: get
sha256: e4e7335ede17452b391ed3b2ede016545706c01a02292a6c97619705e7d2a85e
+2
View File
@@ -24,6 +24,8 @@ dependencies:
flutter_dotenv: 5.0.2
get: 4.6.6
pointer_interceptor: 0.10.1+2
intl: 0.20.2
@@ -68,6 +68,7 @@ import 'package:tmail_ui_user/main/utils/app_config.dart';
import 'package:tmail_ui_user/main/utils/toast_manager.dart';
import 'package:tmail_ui_user/main/utils/twake_app_manager.dart';
import 'package:uuid/uuid.dart';
import 'package:scribe/scribe/ai/domain/usecases/generate_ai_text_interactor.dart';
import '../../../fixtures/account_fixtures.dart';
import '../../../fixtures/session_fixtures.dart';
@@ -178,6 +179,7 @@ class MockMailboxDashBoardController extends Mock implements MailboxDashBoardCon
MockSpec<PrintEmailInteractor>(),
MockSpec<ComposerRepository>(),
MockSpec<SaveTemplateEmailInteractor>(),
MockSpec<GenerateAITextInteractor>(),
// Additional Getx dependencies mock specs
MockSpec<NetworkConnectionController>(fallbackGenerators: fallbackGenerators),
@@ -223,6 +225,7 @@ void main() {
late MockPrintEmailInteractor mockPrintEmailInteractor;
late MockComposerRepository mockComposerRepository;
late MockSaveTemplateEmailInteractor mockSaveTemplateEmailInteractor;
late MockGenerateAITextInteractor mockGenerateAITextInteractor;
// Declaration Getx dependencies
final mockMailboxDashBoardController = MockMailboxDashBoardController();
@@ -293,6 +296,7 @@ void main() {
mockPrintEmailInteractor = MockPrintEmailInteractor();
mockComposerRepository = MockComposerRepository();
mockSaveTemplateEmailInteractor = MockSaveTemplateEmailInteractor();
mockGenerateAITextInteractor = MockGenerateAITextInteractor();
composerController = ComposerController(
mockLocalFilePickerInteractor,
@@ -310,6 +314,7 @@ void main() {
mockPrintEmailInteractor,
mockComposerRepository,
mockSaveTemplateEmailInteractor,
mockGenerateAITextInteractor,
);
mockHtmlEditorApi = MockHtmlEditorApi();