Update video_screen.dart

This commit is contained in:
Anirudh Sevugan 2025-01-21 23:47:14 -06:00 committed by GitHub
parent 52d378ea2b
commit 26fe49a84e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,8 +1,9 @@
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/services.dart'; // Import for SystemChrome
import '../widgets/video_player_widget.dart';
import '../utils/video_player_manager.dart';
// The VideoScreen widget class
class VideoScreen extends StatefulWidget {
const VideoScreen({super.key});
@ -10,15 +11,31 @@ class VideoScreen extends StatefulWidget {
_VideoScreenState createState() => _VideoScreenState();
}
// The State class for VideoScreen
class _VideoScreenState extends State<VideoScreen> {
String _videoUrl = '';
String _filePath = '';
String _subtitleUrl = ''; // Subtitle URL variable
String _subtitleFilePath = ''; // Subtitle file path
bool _isDarkMode = false; // Add theme state here
String _subtitleUrl = '';
String _subtitleFilePath = '';
bool _isDarkMode = false;
// Method to show video URL dialog
// Pick a video or audio file
Future<void> _pickFile() async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.media, // This allows both video and audio file selection
);
if (result != null && result.files.single.path != null) {
setState(() {
_filePath = result.files.single.path!;
_videoUrl = ''; // Clear video URL if file is picked
});
}
}
// Show the dialog to enter video URL
Future<void> _showVideoURLDialog() async {
final TextEditingController videoController = TextEditingController();
@ -26,89 +43,185 @@ class _VideoScreenState extends State<VideoScreen> {
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Enter Video URL'),
content: TextField(
controller: videoController,
decoration: InputDecoration(hintText: 'Enter a valid video URL'),
keyboardType: TextInputType.url,
return Center( // Center the dialog
child: SingleChildScrollView(
child: AlertDialog(
title: const Text('Enter Video URL'),
content: TextField(
controller: videoController,
decoration: const InputDecoration(hintText: 'Enter a valid video URL'),
keyboardType: TextInputType.url,
),
actions: <Widget>[
TextButton(
child: const Text('Cancel'),
onPressed: () => Navigator.of(context).pop(),
),
TextButton(
child: const Text('OK'),
onPressed: () {
setState(() {
_videoUrl = videoController.text;
_filePath = '';
});
Navigator.of(context).pop();
},
),
],
),
),
actions: <Widget>[
TextButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: Text('OK'),
onPressed: () {
setState(() {
_videoUrl = videoController.text;
_filePath = '';
});
Navigator.of(context).pop();
},
),
],
);
},
);
}
// Method to pick video file
Future<void> _pickFile() async {
FilePickerResult? result = await FilePicker.platform.pickFiles(type: FileType.video);
if (result != null && result.files.single.path != null) {
setState(() {
_filePath = result.files.single.path!;
_videoUrl = '';
});
}
}
// Method to pick subtitle file
Future<void> _pickSubtitleFile() async {
FilePickerResult? result = await FilePicker.platform.pickFiles(type: FileType.custom, allowedExtensions: ['vtt']);
if (result != null && result.files.single.path != null) {
setState(() {
_subtitleFilePath = result.files.single.path!;
_subtitleUrl = ''; // Clear subtitle URL when a subtitle file is picked
});
}
}
// Method to enter subtitle URL
Future<void> _enterSubtitleURL() async {
// Show the subtitle dialog
Future<void> _showSubtitleDialog() async {
final TextEditingController subtitleController = TextEditingController();
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Enter Subtitle URL'),
content: TextField(
controller: subtitleController,
decoration: InputDecoration(hintText: 'Enter a valid subtitle URL'),
keyboardType: TextInputType.url,
return Center( // Center the dialog
child: SingleChildScrollView(
child: AlertDialog(
title: const Text('Enter Subtitle URL'),
content: TextField(
controller: subtitleController,
decoration: const InputDecoration(hintText: 'Enter a valid subtitle URL'),
keyboardType: TextInputType.url,
),
actions: <Widget>[
TextButton(
child: const Text('Cancel'),
onPressed: () => Navigator.of(context).pop(),
),
TextButton(
child: const Text('OK'),
onPressed: () {
setState(() {
_subtitleUrl = subtitleController.text;
_subtitleFilePath = ''; // Clear file path when URL is used
});
Navigator.of(context).pop();
},
),
],
),
),
);
},
);
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: _onWillPop, // Use this for back button intercept
child: MaterialApp(
debugShowCheckedModeBanner: false,
themeMode: _isDarkMode ? ThemeMode.dark : ThemeMode.light, // Toggle theme mode
theme: _lightTheme(),
darkTheme: _darkTheme(), // Apply dark theme
home: Scaffold(
appBar: _videoUrl.isNotEmpty || _filePath.isNotEmpty
? null // Hide AppBar when video is playing
: AppBar(
title: const Text('ExoPlayer Creator'),
actions: [
IconButton(
icon: Icon(_isDarkMode ? Icons.light_mode : Icons.dark_mode),
onPressed: () {
setState(() {
_isDarkMode = !_isDarkMode;
});
},
),
],
),
body: Center(
child: _videoUrl.isEmpty && _filePath.isEmpty
? SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 20),
// Enter Video URL Button
Column(
children: [
IconButton(
icon: const Icon(Icons.link, size: 50),
onPressed: _showVideoURLDialog,
),
const Text('Enter Video URL'),
],
),
const SizedBox(height: 20),
// Subtitle URL Button
Column(
children: [
IconButton(
icon: const Icon(Icons.subtitles, size: 50),
onPressed: _showSubtitleDialog,
),
const Text('Add Subtitle URL'),
],
),
const SizedBox(height: 20),
// Choose File Button
Column(
children: [
IconButton(
icon: const Icon(Icons.video_library, size: 50),
onPressed: _pickFile,
),
const Text('Choose File'),
],
),
],
),
)
: VideoPlayerWidget(
videoUrl: _videoUrl,
filePath: _filePath,
subtitleUrl: _subtitleUrl,
subtitleFilePath: _subtitleFilePath,
),
),
),
),
);
}
Future<bool> _onWillPop() async {
// If the video is not playing (i.e., file or URL is empty), exit the app
if (_videoUrl.isEmpty && _filePath.isEmpty) {
return true; // Exit the app
}
// If the video is playing, show the confirmation dialog
return (await _showExitConfirmation()) ?? false;
}
Future<bool?> _showExitConfirmation() async {
return showDialog<bool>(
context: context,
barrierDismissible: false, // Prevent dismissing by tapping outside the dialog
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Are you sure you want to exit?'),
actions: <Widget>[
TextButton(
child: Text('Cancel'),
child: const Text('No'),
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context).pop(false); // Go back to VideoScreen
},
),
TextButton(
child: Text('OK'),
child: const Text('Yes'),
onPressed: () {
setState(() {
_subtitleUrl = subtitleController.text;
});
Navigator.of(context).pop();
Navigator.of(context).pop(true); // Exit the app
},
),
],
@ -117,159 +230,54 @@ class _VideoScreenState extends State<VideoScreen> {
);
}
// Toggle the theme
void _toggleTheme() {
setState(() {
_isDarkMode = !_isDarkMode;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: _isDarkMode
? ThemeData.dark().copyWith(
primaryColor: Colors.blue,
colorScheme: ColorScheme.fromSwatch(
primarySwatch: Colors.lightBlue)
.copyWith(secondary: Colors.blue),
appBarTheme: const AppBarTheme(
color: Colors.blue,
titleTextStyle: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
foregroundColor: Colors.blue,
),
),
inputDecorationTheme: InputDecorationTheme(
filled: true,
fillColor: Colors.white,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(
color: Colors.blue,
width: 2,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(
color: Colors.blue,
width: 2,
),
),
),
)
: ThemeData.light().copyWith(
primaryColor: Colors.blue,
scaffoldBackgroundColor: Colors.white,
colorScheme: ColorScheme.fromSwatch(
primarySwatch: Colors.lightBlue)
.copyWith(secondary: Colors.blue),
appBarTheme: const AppBarTheme(
color: Colors.blue,
titleTextStyle: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
foregroundColor: Colors.blue,
),
),
inputDecorationTheme: InputDecorationTheme(
filled: true,
fillColor: Colors.white,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(
color: Colors.blue,
width: 2,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(
color: Colors.blue,
width: 2,
),
),
),
dialogTheme: DialogTheme(
backgroundColor: Colors.white, // Light background for light mode
titleTextStyle: TextStyle(
color: Colors.black, // Black text for titles in light mode
fontWeight: FontWeight.bold,
),
contentTextStyle: TextStyle(
color: Colors.black, // Black text for content in light mode
),
// Light theme
ThemeData _lightTheme() {
return ThemeData(
primaryColor: Colors.lightBlue,
scaffoldBackgroundColor: Colors.white,
colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.lightBlue)
.copyWith(secondary: Colors.lightBlue),
appBarTheme: AppBarTheme(
color: Colors.lightBlue,
titleTextStyle: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
home: Scaffold(
appBar: _videoUrl.isEmpty && _filePath.isEmpty
? AppBar(
title: const Text('ExoPlayer Creator'),
actions: [
IconButton(
icon: Icon(_isDarkMode ? Icons.light_mode : Icons.dark_mode),
onPressed: _toggleTheme,
),
],
)
: null, // Hide AppBar when video is playing
body: Center(
child: _videoUrl.isEmpty && _filePath.isEmpty
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _showVideoURLDialog,
child: Text('Enter Video URL'),
),
SizedBox(width: 16),
ElevatedButton(
onPressed: _pickFile,
child: Text('Choose Video File'),
),
],
),
SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _enterSubtitleURL,
child: Text('Enter Subtitle URL'),
),
SizedBox(width: 16),
ElevatedButton(
onPressed: _pickSubtitleFile,
child: Text('Choose Subtitle File'),
),
],
),
],
)
: VideoPlayerWidget(
videoUrl: _videoUrl,
filePath: _filePath,
subtitleUrl: _subtitleUrl, // Pass subtitle URL to VideoPlayerWidget
subtitleFilePath: _subtitleFilePath, // Pass subtitle file path to VideoPlayerWidget
),
iconTheme: IconThemeData(
color: Colors.black, // Black icons for light mode
),
textTheme: TextTheme(
bodyLarge: TextStyle(color: Colors.black),
bodyMedium: TextStyle(color: Colors.black),
bodySmall: TextStyle(color: Colors.black),
),
);
}
ThemeData _darkTheme() {
return ThemeData(
primaryColor: Colors.blue, // Primary color for the theme
scaffoldBackgroundColor: Colors.black, // Black background for the scaffold
colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.blue)
.copyWith(secondary: Colors.blue), // Customize color scheme
appBarTheme: AppBarTheme(
color: Colors.blue, // Blue AppBar background
titleTextStyle: TextStyle(
color: Colors.white, // White text on AppBar
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
iconTheme: IconThemeData(
color: Colors.white, // White icons for dark mode
),
textTheme: TextTheme(
bodyLarge: TextStyle(color: Colors.white),
bodyMedium: TextStyle(color: Colors.white),
bodySmall: TextStyle(color: Colors.white),
),
);
}
}