import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart' show kIsWeb; import 'package:provider/provider.dart'; import '../providers/notification_provider.dart'; import 'dart:io'; import '../services/notification_service.dart'; import 'package:url_launcher/url_launcher.dart'; import '../providers/theme_provider.dart'; import '../theme/adaptive_theme.dart'; import '../widgets/glassmorphism_card.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.withValues(alpha: 0.2) : Colors.transparent, borderRadius: BorderRadius.circular(8), border: Border.all( color: isSelected ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.outline.withValues(alpha: 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, ), ), ], ), ), ), ); } @override Widget build(BuildContext context) { return ListView( padding: const EdgeInsets.only(top: 20), children: [ // 테마 설정 GlassmorphismCard( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), padding: const EdgeInsets.all(8), child: Consumer( builder: (context, themeProvider, child) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Padding( padding: EdgeInsets.all(16), child: Text( '테마 설정', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), ), // 테마 모드 선택 ListTile( title: const Text('테마 모드'), subtitle: Text(_getThemeModeText(themeProvider.themeMode)), leading: Icon( _getThemeModeIcon(themeProvider.themeMode), color: Theme.of(context).colorScheme.primary, ), trailing: DropdownButton( value: themeProvider.themeMode, underline: Container(), onChanged: (mode) { if (mode != null) { themeProvider.setThemeMode(mode); } }, items: AppThemeMode.values.map((mode) => DropdownMenuItem( value: mode, child: Text(_getThemeModeText(mode)), ), ).toList(), ), ), const Divider(height: 1), // 접근성 설정 SwitchListTile( title: const Text('큰 텍스트'), subtitle: const Text('텍스트 크기를 크게 표시합니다'), secondary: const Icon(Icons.text_fields), value: themeProvider.largeText, onChanged: themeProvider.setLargeText, ), SwitchListTile( title: const Text('모션 감소'), subtitle: const Text('애니메이션 효과를 줄입니다'), secondary: const Icon(Icons.slow_motion_video), value: themeProvider.reduceMotion, onChanged: themeProvider.setReduceMotion, ), SwitchListTile( title: const Text('고대비 모드'), subtitle: const Text('더 선명한 색상으로 표시합니다'), secondary: const Icon(Icons.contrast), value: themeProvider.highContrast, onChanged: themeProvider.setHighContrast, ), ], ); }, ), ), // 앱 잠금 설정 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(); // } // }, // ); // }, // ), // ), // 알림 설정 GlassmorphismCard( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), padding: const EdgeInsets.all(8), 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 .withValues(alpha: 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 .withValues(alpha: 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 .withValues(alpha: 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); // }, // ), ], ); }, ), ), // 데이터 관리 const GlassmorphismCard( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), padding: const EdgeInsets.all(8), child: const Column( children: [ // 데이터 백업 기능 비활성화 // ListTile( // title: const Text('데이터 백업'), // subtitle: const Text('구독 데이터를 백업합니다'), // leading: const Icon(Icons.backup), // onTap: () => _backupData(context), // ), // const Divider(), ], ), ), // 앱 정보 GlassmorphismCard( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), padding: const EdgeInsets.all(8), 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'), ], ); } }, ), ), SizedBox( height: 20 + MediaQuery.of(context).padding.bottom, // 하단 여백 ), ], ); } String _getThemeModeText(AppThemeMode mode) { switch (mode) { case AppThemeMode.light: return '라이트'; case AppThemeMode.dark: return '다크'; case AppThemeMode.oled: return 'OLED 블랙'; case AppThemeMode.system: return '시스템 설정'; } } IconData _getThemeModeIcon(AppThemeMode mode) { switch (mode) { case AppThemeMode.light: return Icons.light_mode; case AppThemeMode.dark: return Icons.dark_mode; case AppThemeMode.oled: return Icons.phonelink_lock; case AppThemeMode.system: return Icons.settings_brightness; } } }