open ai service

This commit is contained in:
2026-02-08 12:05:05 +06:00
parent d7722ad81d
commit 3209827e92
29 changed files with 2175 additions and 0 deletions

View File

@@ -0,0 +1,126 @@
import 'dart:io';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../models/models.dart';
import '../../services/camera_service.dart';
import '../../services/openai_service.dart';
import 'scanner_event.dart';
import 'scanner_state.dart';
class ScannerBloc extends Bloc<ScannerEvent, ScannerState> {
final CameraService cameraService;
ScannerBloc({required this.cameraService}) : super(const ScannerState()) {
on<InitializeCamera>(_onInitializeCamera);
on<CaptureAndAnalyze>(_onCaptureAndAnalyze);
on<SwitchCamera>(_onSwitchCamera);
on<DismissError>(_onDismissError);
}
Future<void> _onInitializeCamera(
InitializeCamera event,
Emitter<ScannerState> emit,
) async {
try {
final initialized = await cameraService.initializeCamera();
emit(
state.copyWith(
isInitialized: initialized,
hasPermissionError: !initialized,
errorMessage: initialized ? null : 'Нет доступа к камере',
),
);
} catch (e) {
emit(
state.copyWith(
hasPermissionError: true,
errorMessage: 'Ошибка инициализации камеры: $e',
),
);
}
}
Future<void> _onCaptureAndAnalyze(
CaptureAndAnalyze event,
Emitter<ScannerState> emit,
) async {
if (cameraService.controller == null) return;
emit(state.copyWith(isCapturing: true));
try {
// Capture image
final imagePath = await cameraService.captureImage();
if (imagePath == null) {
throw Exception('Не удалось сделать снимок');
}
emit(state.copyWith(isAnalyzing: true, isCapturing: false));
Book? book;
// Try OpenAI first if available
if (event.openaiApiKey != null && event.openaiApiKey!.isNotEmpty) {
print('Using OpenAI service for analysis');
final openaiService = OpenAIService(
apiKey: event.openaiApiKey!,
baseUrl: event.openaiBaseUrl,
);
book = await openaiService.analyzeBookCover(imagePath);
}
// Fall back to Gemini if OpenAI failed or is not configured
// if (book == null) {
// if (event.geminiApiKey == null || event.geminiApiKey!.isEmpty) {
// throw Exception('API ключ не настроен (ни OpenAI, ни Gemini)');
// }
// print('Using Gemini service for analysis');
// final geminiService = GeminiService(apiKey: event.geminiApiKey!);
// book = await geminiService.analyzeBookCover(imagePath);
// }
if (book == null) {
throw Exception('Не удалось распознать книгу');
}
// Clean up temporary image
try {
await File(imagePath).delete();
} catch (e) {
print('Error deleting temporary file: $e');
}
emit(
state.copyWith(
analyzedBook: book,
isAnalyzing: false,
isCapturing: false,
),
);
} catch (e) {
emit(
state.copyWith(
errorMessage: e.toString(),
isCapturing: false,
isAnalyzing: false,
),
);
}
}
Future<void> _onSwitchCamera(
SwitchCamera event,
Emitter<ScannerState> emit,
) async {
await cameraService.switchCamera();
}
void _onDismissError(DismissError event, Emitter<ScannerState> emit) {
emit(state.copyWith(clearError: true));
}
@override
Future<void> close() {
cameraService.dispose();
return super.close();
}
}

View File

@@ -0,0 +1,21 @@
import 'package:books_flutter/config/api_config.dart';
sealed class ScannerEvent {}
class InitializeCamera extends ScannerEvent {}
class CaptureAndAnalyze extends ScannerEvent {
final String? openaiApiKey;
final String openaiBaseUrl;
final String? geminiApiKey;
CaptureAndAnalyze({
this.openaiApiKey,
this.openaiBaseUrl = ApiConfig.openaiBaseUrl,
this.geminiApiKey,
});
}
class SwitchCamera extends ScannerEvent {}
class DismissError extends ScannerEvent {}

View File

@@ -0,0 +1,39 @@
import '../../models/models.dart';
class ScannerState {
final bool isInitialized;
final bool isCapturing;
final bool isAnalyzing;
final bool hasPermissionError;
final String? errorMessage;
final Book? analyzedBook;
const ScannerState({
this.isInitialized = false,
this.isCapturing = false,
this.isAnalyzing = false,
this.hasPermissionError = false,
this.errorMessage,
this.analyzedBook,
});
ScannerState copyWith({
bool? isInitialized,
bool? isCapturing,
bool? isAnalyzing,
bool? hasPermissionError,
String? errorMessage,
Book? analyzedBook,
bool clearError = false,
bool clearBook = false,
}) {
return ScannerState(
isInitialized: isInitialized ?? this.isInitialized,
isCapturing: isCapturing ?? this.isCapturing,
isAnalyzing: isAnalyzing ?? this.isAnalyzing,
hasPermissionError: hasPermissionError ?? this.hasPermissionError,
errorMessage: clearError ? null : (errorMessage ?? this.errorMessage),
analyzedBook: clearBook ? null : (analyzedBook ?? this.analyzedBook),
);
}
}