Extract AI Scribe suggestion logic
In Scribe desktop, the suggestion is displayed in a popup. In Scribe mobile, it will be displayed in a full screen modal. But it share the same logic about loading, success and error. So here I extract this logic and use it in the AI Scribe desktop to be able to use it later in AI Scribe mobile.
This commit is contained in:
@@ -25,6 +25,7 @@ export 'scribe/ai/presentation/utils/ai_scribe_constants.dart';
|
||||
export 'scribe/ai/presentation/utils/context_menu/hover_submenu_controller.dart';
|
||||
export 'scribe/ai/presentation/utils/context_menu/context_submenu_controller.dart';
|
||||
export 'scribe/ai/presentation/utils/modal/ai_scribe_modal_manager.dart';
|
||||
export 'scribe/ai/presentation/utils/modal/ai_scribe_suggestion_state_mixin.dart';
|
||||
export 'scribe/ai/presentation/utils/modal/anchored_modal_layout_calculator.dart';
|
||||
export 'scribe/ai/presentation/widgets/button/ai_assistant_button.dart';
|
||||
export 'scribe/ai/presentation/widgets/button/inline_ai_assist_button.dart';
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:dartz/dartz.dart' as dartz;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:scribe/scribe.dart';
|
||||
import 'package:scribe/scribe/ai/data/network/ai_api_exception.dart';
|
||||
|
||||
mixin AiScribeSuggestionStateMixin<T extends StatefulWidget> on State<T> {
|
||||
GenerateAITextInteractor? get interactor => _interactor;
|
||||
GenerateAITextInteractor? _interactor;
|
||||
|
||||
ValueNotifier<dartz.Either<Failure, Success>> get suggestionState => _suggestionState;
|
||||
final ValueNotifier<dartz.Either<Failure, Success>> _suggestionState =
|
||||
ValueNotifier(dartz.Right(GenerateAITextLoading()));
|
||||
|
||||
AIAction get aiAction;
|
||||
String? get content;
|
||||
ImagePaths get imagePaths;
|
||||
OnSelectAiScribeSuggestionAction get onSelectAction;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
if (!Get.isRegistered<GenerateAITextInteractor>()) {
|
||||
_suggestionState.value = dartz.Left(
|
||||
GenerateAITextFailure(
|
||||
GenerateAITextInteractorIsNotRegisteredException(),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
_interactor = Get.find<GenerateAITextInteractor>();
|
||||
loadSuggestion();
|
||||
}
|
||||
|
||||
Future<void> loadSuggestion() async {
|
||||
_suggestionState.value = dartz.Right(GenerateAITextLoading());
|
||||
|
||||
final result = await _interactor!.execute(
|
||||
aiAction,
|
||||
content,
|
||||
);
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
result.fold(
|
||||
(failure) => _suggestionState.value = dartz.Left(failure),
|
||||
(success) => _suggestionState.value = dartz.Right(success),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildStateContent(
|
||||
BuildContext context,
|
||||
ScribeLocalizations localizations,
|
||||
) {
|
||||
return ValueListenableBuilder<dartz.Either<Failure, Success>>(
|
||||
valueListenable: _suggestionState,
|
||||
builder: (_, stateValue, __) {
|
||||
return stateValue.fold(
|
||||
(failure) => buildErrorState(localizations),
|
||||
(value) {
|
||||
if (value is GenerateAITextSuccess) {
|
||||
final hasContent = content?.trim().isNotEmpty == true;
|
||||
|
||||
return buildSuccessState(
|
||||
value.response.result,
|
||||
hasContent,
|
||||
localizations,
|
||||
);
|
||||
}
|
||||
return buildLoadingState(localizations);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildLoadingState(ScribeLocalizations localizations) {
|
||||
return AiScribeSuggestionLoading(
|
||||
imagePaths: imagePaths,
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildErrorState(ScribeLocalizations localizations) {
|
||||
return AiScribeSuggestionError(
|
||||
imagePaths: imagePaths,
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildSuccessState(
|
||||
String suggestionText,
|
||||
bool hasContent,
|
||||
ScribeLocalizations localizations,
|
||||
) {
|
||||
return AiScribeSuggestionSuccess(
|
||||
imagePaths: imagePaths,
|
||||
suggestionText: suggestionText,
|
||||
hasContent: hasContent,
|
||||
onSelectAction: onSelectAction,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_suggestionState.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,9 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:dartz/dartz.dart' as dartz;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||
import 'package:scribe/scribe.dart';
|
||||
import 'package:scribe/scribe/ai/data/network/ai_api_exception.dart';
|
||||
|
||||
class AiScribeSuggestionWidget extends StatefulWidget {
|
||||
final AIAction aiAction;
|
||||
@@ -37,42 +32,20 @@ class AiScribeSuggestionWidget extends StatefulWidget {
|
||||
_AiScribeSuggestionWidgetState();
|
||||
}
|
||||
|
||||
class _AiScribeSuggestionWidgetState extends State<AiScribeSuggestionWidget> {
|
||||
GenerateAITextInteractor? _interactor;
|
||||
|
||||
final ValueNotifier<dartz.Either<Failure, Success>> _state =
|
||||
ValueNotifier(dartz.Right(GenerateAITextLoading()));
|
||||
class _AiScribeSuggestionWidgetState extends State<AiScribeSuggestionWidget>
|
||||
with AiScribeSuggestionStateMixin {
|
||||
@override
|
||||
AIAction get aiAction => widget.aiAction;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
String? get content => widget.content;
|
||||
|
||||
if (!Get.isRegistered<GenerateAITextInteractor>()) {
|
||||
_state.value = dartz.Left(
|
||||
GenerateAITextFailure(
|
||||
const GenerateAITextInteractorIsNotRegisteredException(),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
@override
|
||||
ImagePaths get imagePaths => widget.imagePaths;
|
||||
|
||||
_interactor = Get.find<GenerateAITextInteractor>();
|
||||
_loadSuggestion();
|
||||
}
|
||||
|
||||
Future<void> _loadSuggestion() async {
|
||||
final result = await _interactor!.execute(
|
||||
widget.aiAction,
|
||||
widget.content,
|
||||
);
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
result.fold(
|
||||
(failure) => _state.value = dartz.Left(failure),
|
||||
(success) => _state.value = dartz.Right(success),
|
||||
);
|
||||
}
|
||||
@override
|
||||
OnSelectAiScribeSuggestionAction get onSelectAction =>
|
||||
widget.onSelectAiScribeSuggestionAction;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -147,30 +120,7 @@ class _AiScribeSuggestionWidgetState extends State<AiScribeSuggestionWidget> {
|
||||
imagePaths: widget.imagePaths,
|
||||
),
|
||||
Flexible(
|
||||
child: ValueListenableBuilder<dartz.Either<Failure, Success>>(
|
||||
valueListenable: _state,
|
||||
builder: (_, state, __) {
|
||||
return state.fold(
|
||||
(_) => AiScribeSuggestionError(
|
||||
imagePaths: widget.imagePaths,
|
||||
),
|
||||
(value) {
|
||||
if (value is GenerateAITextSuccess) {
|
||||
return AiScribeSuggestionSuccess(
|
||||
imagePaths: widget.imagePaths,
|
||||
suggestionText: value.response.result,
|
||||
hasContent: hasContent,
|
||||
onSelectAction: widget.onSelectAiScribeSuggestionAction,
|
||||
);
|
||||
}
|
||||
|
||||
return AiScribeSuggestionLoading(
|
||||
imagePaths: widget.imagePaths,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
child: buildStateContent(context, localizations),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -205,7 +155,7 @@ class _AiScribeSuggestionWidgetState extends State<AiScribeSuggestionWidget> {
|
||||
widget.buttonPosition != null && widget.buttonSize != null;
|
||||
|
||||
void _handleClickOutside() {
|
||||
final shouldDismiss = _state.value.fold(
|
||||
final shouldDismiss = suggestionState.value.fold(
|
||||
(failure) => failure is GenerateAITextFailure,
|
||||
(success) => success is GenerateAITextSuccess,
|
||||
);
|
||||
@@ -213,10 +163,4 @@ class _AiScribeSuggestionWidgetState extends State<AiScribeSuggestionWidget> {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_state.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user