import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; // SystemChrome, DeviceOrientation 사용을 위해 import import 'package:youtube_player_flutter/youtube_player_flutter.dart'; import 'common/widgets/custom_bottom_nav_bar.dart'; class YoutubePlayerPage extends StatefulWidget { final String lessonUrl; final void Function(bool isFullScreen)? onFullScreenToggle; const YoutubePlayerPage({ super.key, required this.lessonUrl, this.onFullScreenToggle, }); @override State createState() => _YoutubePlayerPageState(); } class _YoutubePlayerPageState extends State { YoutubePlayerController? _controller; String? _videoId; bool _isPlayerReady = false; String _videoTitle = 'YouTube Video'; final int _currentBottomNavIndex = 0; bool _isSystemUiVisible = true; bool _isLoading = true; // 로딩 상태 추가 bool _isFullScreen = false; @override void initState() { super.initState(); _videoId = YoutubePlayer.convertUrlToId(widget.lessonUrl); WidgetsBinding.instance.addPostFrameCallback((_) { if (mounted) { final String snackBarMessage; if (_videoId != null) { snackBarMessage = 'Video ID: $_videoId'; } else { snackBarMessage = 'Could not extract Video ID from URL: ${widget.lessonUrl}'; } ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(snackBarMessage), duration: const Duration(seconds: 3), ), ); } }); if (_videoId != null) { _controller = YoutubePlayerController( initialVideoId: _videoId!, flags: const YoutubePlayerFlags( autoPlay: true, mute: false, ), )..addListener(_playerListener); } else { _videoTitle = 'Video Error'; } } void _playerListener() { if (_controller == null || !mounted) return; if (_isFullScreen != _controller!.value.isFullScreen) { setState(() { _isFullScreen = _controller!.value.isFullScreen; }); widget.onFullScreenToggle?.call(_isFullScreen); if (_isFullScreen) { _hideSystemUi(); } else { _showSystemUi(); SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); } } if (_controller!.value.playerState == PlayerState.ended) { if (mounted) { if (_controller!.value.isFullScreen) { _controller!.toggleFullScreenMode(); } } return; } if (_isPlayerReady) { if (_controller!.metadata.title.isNotEmpty && _videoTitle != _controller!.metadata.title) { if (mounted) { setState(() { _videoTitle = _controller!.metadata.title; }); } } } } void _hideSystemUi() { if (!_isSystemUiVisible) return; SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); if (mounted) { setState(() { _isSystemUiVisible = false; }); } } void _showSystemUi() { if (_isSystemUiVisible) return; SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); if (mounted) { setState(() { _isSystemUiVisible = true; }); } } void _onNotificationTapped() { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('알림 아이콘 클릭됨')), ); } void _onProfileTapped() { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('프로필 아이콘 클릭됨')), ); } void _onBottomNavItemTapped(int index) { if (_currentBottomNavIndex == index && index != 0) return; if (index == 0) { Navigator.of(context).popUntil((route) => route.isFirst); } else { String tabName = ''; switch (index) { case 1: tabName = 'Plan'; break; case 2: tabName = 'Statistics'; break; case 3: tabName = 'Career'; // New case for Jobs break; case 4: tabName = 'More'; // Updated case for More break; } ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('$tabName 탭으로 이동 (구현 필요)')), ); } } @override void didUpdateWidget(covariant YoutubePlayerPage oldWidget) { super.didUpdateWidget(oldWidget); if (widget.lessonUrl != oldWidget.lessonUrl) { _videoId = YoutubePlayer.convertUrlToId(widget.lessonUrl); if (_videoId != null) { _controller?.load(_videoId!); // 새 비디오 로드 } else { if (mounted) { setState(() { _videoTitle = 'Video Error'; }); } } } } // <<< 뒤로가기 버튼 처리 로직 >>> Future _onWillPop() async { if (_controller != null && _controller!.value.isFullScreen) { _controller!.toggleFullScreenMode(); // 전체 화면 해제 // _playerListener에서 화면 방향은 자동으로 세로로 설정될 것임 // _showSystemUi(); // 시스템 UI도 _playerListener에서 처리 return false; // 뒤로가기(페이지 pop) 막음 } // 전체 화면이 아닐 때는 일반적인 뒤로 가기 동작 허용 return true; } @override Widget build(BuildContext context) { final bool isFullScreen = _controller?.value.isFullScreen ?? false; // <<< WillPopScope로 Scaffold를 감싸서 뒤로가기 이벤트 가로채기 >>> return WillPopScope( onWillPop: _onWillPop, child: Scaffold( extendBodyBehindAppBar: isFullScreen, body: Column( // <--- Wrap the body content in a Column children: [ Expanded( // <--- Wrap the main content with Expanded child: Center( child: _controller == null ? Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error_outline, color: Colors.red, size: 50), const SizedBox(height: 10), Padding( padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Text( '비디오를 로드할 수 없습니다.\nURL: ${widget.lessonUrl}', textAlign: TextAlign.center, style: const TextStyle(fontSize: 16), overflow: TextOverflow.ellipsis, ), ), ], ) : YoutubePlayer( controller: _controller!, showVideoProgressIndicator: true, progressIndicatorColor: Colors.amber, progressColors: const ProgressBarColors( playedColor: Colors.amber, handleColor: Colors.amberAccent, ), onReady: () { if (mounted) { setState(() { _isPlayerReady = true; if (_controller!.metadata.title.isNotEmpty) { _videoTitle = _controller!.metadata.title; } }); } }, ), ), ), ], ), bottomNavigationBar: isFullScreen ? null : CustomBottomNavBar( currentIndex: _currentBottomNavIndex, onTap: _onBottomNavItemTapped, ), ), ); } @override void deactivate() { // 페이지가 비활성화될 때 (예: 다른 화면으로 전환될 때) 플레이어 일시 중지 if (_controller != null && _isPlayerReady && _controller!.value.isPlaying) { _controller!.pause(); } super.deactivate(); } @override void dispose() { // <<< 페이지 종료 시 기본 화면 방향으로 복구 또는 모든 방향 허용 >>> SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, // DeviceOrientation.landscapeLeft, // 필요에 따라 가로모드도 허용 // DeviceOrientation.landscapeRight, ]); // 또는: SystemChrome.setPreferredOrientations(DeviceOrientation.values); // 모든 방향 허용 // 시스템 UI 복구 (이미 _showSystemUi()가 있지만, 명시적으로 호출) // _showSystemUi(); // 이 로직은 _isSystemUiVisible 상태에 따라 실행되므로 안전 // 또는 강제로 UI를 보이게 하려면: SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); _controller?.removeListener(_playerListener); _controller?.dispose(); super.dispose(); } }