Files
bookshelf/books_flutter/lib/bloc/scanner/scanner_bloc.dart
2026-02-08 12:05:05 +06:00

127 lines
3.5 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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();
}
}