Files
submanager/lib/screens/sms_scan_screen.dart
JiWoong Sul 186d1bbf66 feat: SMS 스캔 화면 리팩토링 및 MVC 패턴 적용
- SMS 스캔 화면을 컨트롤러/서비스/위젯으로 분리
- 코드 가독성 및 유지보수성 향상
- 새로운 다국어 지원 키 추가
- Git 커밋 가이드라인 문서화
2025-07-17 16:59:19 +09:00

122 lines
3.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../controllers/sms_scan_controller.dart';
import '../widgets/sms_scan/scan_loading_widget.dart';
import '../widgets/sms_scan/scan_initial_widget.dart';
import '../widgets/sms_scan/scan_progress_widget.dart';
import '../widgets/sms_scan/subscription_card_widget.dart';
import '../widgets/common/snackbar/app_snackbar.dart';
import '../l10n/app_localizations.dart';
class SmsScanScreen extends StatefulWidget {
const SmsScanScreen({super.key});
@override
State<SmsScanScreen> createState() => _SmsScanScreenState();
}
class _SmsScanScreenState extends State<SmsScanScreen> {
late SmsScanController _controller;
@override
void initState() {
super.initState();
_controller = SmsScanController();
_controller.addListener(_handleControllerUpdate);
}
@override
void dispose() {
_controller.removeListener(_handleControllerUpdate);
_controller.dispose();
super.dispose();
}
void _handleControllerUpdate() {
if (mounted) {
setState(() {});
}
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
_controller.initializeWebsiteUrl();
}
Widget _buildContent() {
if (_controller.isLoading) {
return const ScanLoadingWidget();
}
if (_controller.scannedSubscriptions.isEmpty) {
return ScanInitialWidget(
onScanPressed: () => _controller.scanSms(context),
errorMessage: _controller.errorMessage,
);
}
// 모든 구독 처리 완료 확인
if (_controller.currentIndex >= _controller.scannedSubscriptions.length) {
// 중복 스낵바 방지를 위해 바로 초기 화면으로
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted && _controller.scannedSubscriptions.isNotEmpty) {
AppSnackBar.showSuccess(
context: context,
message: AppLocalizations.of(context).allSubscriptionsProcessed,
);
// 상태 초기화
_controller.resetState();
}
});
return ScanInitialWidget(
onScanPressed: () => _controller.scanSms(context),
errorMessage: _controller.errorMessage,
);
}
final currentSubscription = _controller.scannedSubscriptions[_controller.currentIndex];
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: ScanProgressWidget(
currentIndex: _controller.currentIndex,
totalCount: _controller.scannedSubscriptions.length,
),
),
const SizedBox(height: 24),
SubscriptionCardWidget(
subscription: currentSubscription,
websiteUrlController: _controller.websiteUrlController,
selectedCategoryId: _controller.selectedCategoryId,
onCategoryChanged: _controller.setSelectedCategoryId,
onAdd: () => _controller.addCurrentSubscription(context),
onSkip: () => _controller.skipCurrentSubscription(context),
),
],
);
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
padding: EdgeInsets.zero,
child: Column(
children: [
// toolbar 높이 추가
SizedBox(
height: kToolbarHeight + MediaQuery.of(context).padding.top,
),
_buildContent(),
// FloatingNavigationBar를 위한 충분한 하단 여백
SizedBox(
height: 120 + MediaQuery.of(context).padding.bottom,
),
],
),
);
}
}