import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart' show kIsWeb; import 'package:provider/provider.dart'; import '../providers/app_lock_provider.dart'; import '../providers/notification_provider.dart'; import '../providers/subscription_provider.dart'; import 'package:share_plus/share_plus.dart'; import 'package:path_provider/path_provider.dart'; import 'dart:io'; import 'package:path/path.dart' as path; import '../services/notification_service.dart'; import '../screens/sms_scan_screen.dart'; import 'package:url_launcher/url_launcher.dart'; class SettingsScreen extends StatelessWidget { const SettingsScreen({super.key}); // 알림 시점 라디오 버튼 생성 헬퍼 메서드 Widget _buildReminderDayRadio(BuildContext context, NotificationProvider provider, int value, String label) { final isSelected = provider.reminderDays == value; return Expanded( child: InkWell( onTap: () => provider.setReminderDays(value), child: Container( margin: const EdgeInsets.symmetric(horizontal: 4), padding: const EdgeInsets.symmetric(vertical: 10), decoration: BoxDecoration( color: isSelected ? Theme.of(context).colorScheme.primary.withOpacity(0.2) : Colors.transparent, borderRadius: BorderRadius.circular(8), border: Border.all( color: isSelected ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.outline.withOpacity(0.5), width: isSelected ? 2 : 1, ), ), child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked, color: isSelected ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.outline, size: 24, ), const SizedBox(height: 6), Text( label, style: TextStyle( fontSize: 14, fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, color: isSelected ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onSurface, ), ), ], ), ), ), ); } Future _backupData(BuildContext context) async { try { final provider = context.read(); final subscriptions = provider.subscriptions; // 임시 디렉토리에 백업 파일 생성 final tempDir = await getTemporaryDirectory(); final backupFile = File(path.join(tempDir.path, 'submanager_backup.json')); // 구독 데이터를 JSON 형식으로 저장 final jsonData = subscriptions .map((sub) => { 'id': sub.id, 'serviceName': sub.serviceName, 'monthlyCost': sub.monthlyCost, 'billingCycle': sub.billingCycle, 'nextBillingDate': sub.nextBillingDate.toIso8601String(), 'isAutoDetected': sub.isAutoDetected, 'repeatCount': sub.repeatCount, 'lastPaymentDate': sub.lastPaymentDate?.toIso8601String(), }) .toList(); await backupFile.writeAsString(jsonData.toString()); // 파일 공유 await Share.shareXFiles( [XFile(backupFile.path)], text: 'SubManager 백업 파일', ); if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('백업 파일이 생성되었습니다')), ); } } catch (e) { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('백업 중 오류가 발생했습니다: $e')), ); } } } // SMS 스캔 화면으로 이동 void _navigateToSmsScan(BuildContext context) async { final added = await Navigator.push( context, MaterialPageRoute(builder: (context) => const SmsScanScreen()), ); if (added == true && context.mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('구독이 성공적으로 추가되었습니다')), ); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('설정'), ), body: ListView( children: [ // 앱 잠금 설정 UI 숨김 // Card( // margin: const EdgeInsets.all(16), // child: Consumer( // builder: (context, provider, child) { // return SwitchListTile( // title: const Text('앱 잠금'), // subtitle: const Text('생체 인증으로 앱 잠금'), // value: provider.isEnabled, // onChanged: (value) async { // if (value) { // final isAuthenticated = await provider.authenticate(); // if (isAuthenticated) { // provider.enable(); // } // } else { // provider.disable(); // } // }, // ); // }, // ), // ), // 알림 설정 Card( margin: const EdgeInsets.symmetric(horizontal: 16), child: Consumer( builder: (context, provider, child) { return Column( children: [ ListTile( title: const Text('알림 권한'), subtitle: const Text('알림을 받으려면 권한이 필요합니다'), trailing: ElevatedButton( onPressed: () async { final granted = await NotificationService.requestPermission(); if (granted) { provider.setEnabled(true); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('알림 권한이 거부되었습니다'), ), ); } }, child: const Text('권한 요청'), ), ), const Divider(), // 결제 예정 알림 기본 스위치 SwitchListTile( title: const Text('결제 예정 알림'), subtitle: const Text('결제 예정일 알림 받기'), value: provider.isPaymentEnabled, onChanged: (value) { provider.setPaymentEnabled(value); }, ), // 알림 세부 설정 (알림 활성화된 경우에만 표시) AnimatedSize( duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, child: provider.isPaymentEnabled ? Padding( padding: const EdgeInsets.only( left: 16.0, right: 16.0, bottom: 8.0), child: Card( elevation: 0, color: Theme.of(context) .colorScheme .surfaceVariant .withOpacity(0.3), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), child: Padding( padding: const EdgeInsets.all(12.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 알림 시점 선택 (1일전, 2일전, 3일전) const Text('알림 시점', style: TextStyle( fontWeight: FontWeight.bold)), const SizedBox(height: 8), Padding( padding: const EdgeInsets.symmetric( vertical: 8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildReminderDayRadio( context, provider, 1, '1일 전'), _buildReminderDayRadio( context, provider, 2, '2일 전'), _buildReminderDayRadio( context, provider, 3, '3일 전'), ], ), ), const SizedBox(height: 16), // 알림 시간 선택 const Text('알림 시간', style: TextStyle( fontWeight: FontWeight.bold)), const SizedBox(height: 12), InkWell( onTap: () async { final TimeOfDay? picked = await showTimePicker( context: context, initialTime: TimeOfDay( hour: provider.reminderHour, minute: provider.reminderMinute), ); if (picked != null) { provider.setReminderTime( picked.hour, picked.minute); } }, child: Container( padding: const EdgeInsets.symmetric( vertical: 12, horizontal: 16), decoration: BoxDecoration( border: Border.all( color: Theme.of(context) .colorScheme .outline .withOpacity(0.5), ), borderRadius: BorderRadius.circular(8), ), child: Row( children: [ Expanded( child: Row( children: [ Icon( Icons.access_time, color: Theme.of(context) .colorScheme .primary, size: 22, ), const SizedBox(width: 12), Text( '${provider.reminderHour.toString().padLeft(2, '0')}:${provider.reminderMinute.toString().padLeft(2, '0')}', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Theme.of(context) .colorScheme .onSurface, ), ), ], ), ), Icon( Icons.arrow_forward_ios, size: 16, color: Theme.of(context) .colorScheme .outline, ), ], ), ), ), // 반복 알림 스위치 (2일전, 3일전 선택 시에만 활성화) if (provider.reminderDays >= 2) Padding( padding: const EdgeInsets.only(top: 16.0), child: Container( padding: const EdgeInsets.symmetric( vertical: 4, horizontal: 4), decoration: BoxDecoration( color: Theme.of(context) .colorScheme .surfaceVariant .withOpacity(0.3), borderRadius: BorderRadius.circular(8), ), child: SwitchListTile( contentPadding: const EdgeInsets.symmetric( horizontal: 12), title: const Text('1일마다 반복 알림'), subtitle: const Text( '결제일까지 매일 알림을 받습니다'), value: provider .isDailyReminderEnabled, activeColor: Theme.of(context) .colorScheme .primary, onChanged: (value) { provider .setDailyReminderEnabled( value); }, ), ), ), ], ), ), ), ) : const SizedBox.shrink(), ), // 미사용 서비스 알림 기능 비활성화 // const Divider(), // SwitchListTile( // title: const Text('미사용 서비스 알림'), // subtitle: const Text('2개월 이상 미사용 시 알림'), // value: provider.isUnusedServiceNotificationEnabled, // onChanged: (value) { // provider.setUnusedServiceNotificationEnabled(value); // }, // ), ], ); }, ), ), // 데이터 관리 Card( margin: const EdgeInsets.all(16), child: Column( children: [ // 데이터 백업 기능 비활성화 // ListTile( // title: const Text('데이터 백업'), // subtitle: const Text('구독 데이터를 백업합니다'), // leading: const Icon(Icons.backup), // onTap: () => _backupData(context), // ), // const Divider(), // SMS 스캔 - 시각적으로 강조된 UI InkWell( onTap: () => _navigateToSmsScan(context), child: Container( decoration: BoxDecoration( gradient: LinearGradient( colors: [ Theme.of(context).primaryColor.withOpacity(0.1), Theme.of(context).primaryColor.withOpacity(0.2), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(12), bottomRight: Radius.circular(12), ), ), child: Padding( padding: const EdgeInsets.symmetric( vertical: 16.0, horizontal: 8.0), child: Row( children: [ Container( padding: const EdgeInsets.all(12), margin: const EdgeInsets.only(left: 8, right: 16), decoration: BoxDecoration( color: Theme.of(context) .primaryColor .withOpacity(0.15), borderRadius: BorderRadius.circular(12), ), child: Icon( Icons.sms_rounded, color: Theme.of(context).primaryColor, size: 28, ), ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( 'SMS 스캔으로 구독 자동 찾기', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, color: Theme.of(context).primaryColor, ), ), const SizedBox(width: 6), Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 3, ), decoration: BoxDecoration( color: Theme.of(context).primaryColor, borderRadius: BorderRadius.circular(12), ), child: const Text( '추천', style: TextStyle( color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold, ), ), ), ], ), const SizedBox(height: 6), const Text( '2회 이상 반복 결제된 구독 서비스를 자동으로 찾아 추가합니다', style: TextStyle( color: Colors.black54, fontSize: 13, ), ), ], ), ), Icon( Icons.arrow_forward_ios, size: 16, color: Theme.of(context).primaryColor, ), const SizedBox(width: 16), ], ), ), ), ), ], ), ), // 앱 정보 Card( margin: const EdgeInsets.symmetric(horizontal: 16), child: ListTile( title: const Text('앱 정보'), subtitle: const Text('버전 1.0.0'), leading: const Icon(Icons.info), onTap: () async { // 웹 환경에서는 기본 다이얼로그 표시 if (kIsWeb) { showAboutDialog( context: context, applicationName: 'SubManager', applicationVersion: '1.0.0', applicationIcon: const FlutterLogo(size: 50), children: [ const Text('구독 관리 앱'), const SizedBox(height: 8), const Text('개발자: SubManager Team'), ], ); return; } // 앱 스토어 링크 String storeUrl = ''; // 플랫폼에 따라 스토어 링크 설정 if (Platform.isAndroid) { // Android - Google Play 스토어 링크 storeUrl = 'https://play.google.com/store/apps/details?id=com.submanager.app'; } else if (Platform.isIOS) { // iOS - App Store 링크 storeUrl = 'https://apps.apple.com/app/submanager/id123456789'; } if (storeUrl.isNotEmpty) { try { final Uri url = Uri.parse(storeUrl); await launchUrl(url, mode: LaunchMode.externalApplication); } catch (e) { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('스토어를 열 수 없습니다')), ); } } } else { // 스토어 링크를 열 수 없는 경우 기존 정보 다이얼로그 표시 showAboutDialog( context: context, applicationName: 'SubManager', applicationVersion: '1.0.0', applicationIcon: const FlutterLogo(size: 50), children: [ const Text('구독 관리 앱'), const SizedBox(height: 8), const Text('개발자: SubManager Team'), ], ); } }, ), ), ], ), ); } }