diff --git a/lib/components/custom_app_bar.dart b/lib/components/custom_app_bar.dart index ea7f0dd..e7a21b8 100644 --- a/lib/components/custom_app_bar.dart +++ b/lib/components/custom_app_bar.dart @@ -2,15 +2,16 @@ import "package:flutter/material.dart"; import 'package:prayer_time_app/config.dart'; import '../utils.dart'; -AppBar customAppBar(BuildContext context, String title, {bool back = true}) { +AppBar customAppBar(BuildContext context, String title, {bool back = true, List? actions}) { return AppBar( title: Text(title), elevation: 1, centerTitle: false, automaticallyImplyLeading: back, actions: [ + if (actions != null) ...actions, IconButton( - icon: Icon(Icons.wb_sunny), + icon: const Icon(Icons.wb_sunny), onPressed: () => { currentTheme.switchTheme(), }, diff --git a/lib/main.dart b/lib/main.dart index c601045..1b86616 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,6 +9,8 @@ import 'package:prayer_time_app/theme.dart'; import 'package:prayer_time_app/MainNavigation.dart'; import 'package:prayer_time_app/services/notification_service.dart'; import 'package:prayer_time_app/services/widget_service.dart'; +import 'package:prayer_time_app/services/tasbih_provider.dart'; +import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; Future main() async { @@ -84,19 +86,24 @@ class _PrayerTimeAppState extends State { @override Widget build(BuildContext context) { - return MaterialApp( - title: "Prayers Time", - home: MainNavigation(latitude: widget.latitude, longitude: widget.longitude, method: widget.method), - theme: lightTheme(), - darkTheme: darkTheme(), - themeMode: currentTheme.currentTheme(theme: widget.theme), - routes: { - 'home': (context) => MainNavigation(latitude: widget.latitude, longitude: widget.longitude, method: widget.method), - 'extend': (context) => Monthly(latitude: widget.latitude!, longitude: widget.longitude!, method: widget.method), - 'settings': (context) => Settings(latitude: widget.latitude, longitude: widget.longitude, method: widget.method), - 'about': (context) => About(), - }, - debugShowCheckedModeBanner: false, + return MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => TasbihProvider()), + ], + child: MaterialApp( + title: "Prayers Time", + home: MainNavigation(latitude: widget.latitude, longitude: widget.longitude, method: widget.method), + theme: lightTheme(), + darkTheme: darkTheme(), + themeMode: currentTheme.currentTheme(theme: widget.theme), + routes: { + 'home': (context) => MainNavigation(latitude: widget.latitude, longitude: widget.longitude, method: widget.method), + 'extend': (context) => Monthly(latitude: widget.latitude!, longitude: widget.longitude!, method: widget.method), + 'settings': (context) => Settings(latitude: widget.latitude, longitude: widget.longitude, method: widget.method), + 'about': (context) => About(), + }, + debugShowCheckedModeBanner: false, + ), ); } } diff --git a/lib/pages/TasbihFullScreenPage.dart b/lib/pages/TasbihFullScreenPage.dart new file mode 100644 index 0000000..bd2760c --- /dev/null +++ b/lib/pages/TasbihFullScreenPage.dart @@ -0,0 +1,140 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:prayer_time_app/services/tasbih_provider.dart'; + +class TasbihFullScreenPage extends StatelessWidget { + const TasbihFullScreenPage({super.key}); + + @override + Widget build(BuildContext context) { + final tasbih = Provider.of(context); + final isDark = Theme.of(context).brightness == Brightness.dark; + + return Scaffold( + body: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: isDark + ? [const Color(0xFF0f0f1e), const Color(0xFF1a1a2e)] + : [const Color(0xFFf5f7fa), const Color(0xFFc3cfe2)], + ), + ), + child: SafeArea( + child: Column( + children: [ + // Top Bar + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Row( + children: [ + IconButton( + icon: const Icon(Icons.close_rounded, size: 28), + onPressed: () => Navigator.pop(context), + tooltip: "Exit Full Screen", + ), + const Spacer(), + Text( + "Goal: ${tasbih.goal}", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: isDark ? Colors.white70 : Colors.black54, + ), + ), + const Spacer(), + IconButton( + icon: const Icon(Icons.settings_outlined, size: 24), + onPressed: () => _showGoalDialog(context, tasbih), + tooltip: "Set Goal", + ), + IconButton( + icon: const Icon(Icons.refresh_rounded, size: 24), + onPressed: tasbih.reset, + tooltip: "Reset Counter", + ), + ], + ), + ), + // Main Tap Area + Expanded( + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: tasbih.increment, + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "${tasbih.counter}", + style: TextStyle( + fontSize: 120, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : const Color(0xFF2d3436), + shadows: [ + Shadow( + color: (isDark ? Colors.black : Colors.black12).withOpacity(0.3), + blurRadius: 20, + offset: const Offset(0, 5), + ), + ], + ), + ), + const SizedBox(height: 10), + Text( + "TAP ANYWHERE", + style: TextStyle( + fontSize: 14, + letterSpacing: 2, + fontWeight: FontWeight.w500, + color: isDark ? Colors.white38 : Colors.black26, + ), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ), + ); + } + + void _showGoalDialog(BuildContext context, TasbihProvider tasbih) { + int tempGoal = tasbih.goal; + final controller = TextEditingController(text: tasbih.goal.toString()); + + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text("Set Tasbih Goal"), + content: TextField( + controller: controller, + keyboardType: TextInputType.number, + autofocus: true, + decoration: const InputDecoration(hintText: "Enter goal (e.g., 33, 100)"), + onChanged: (value) { + tempGoal = int.tryParse(value) ?? tasbih.goal; + }, + ), + actions: [ + TextButton(onPressed: () => Navigator.pop(context), child: const Text("Cancel")), + TextButton( + onPressed: () { + tasbih.setGoal(tempGoal); + Navigator.pop(context); + }, + child: const Text("Set"), + ), + ], + ); + }, + ); + } +} diff --git a/lib/pages/TasbihPage.dart b/lib/pages/TasbihPage.dart index 19657e3..e2006a4 100644 --- a/lib/pages/TasbihPage.dart +++ b/lib/pages/TasbihPage.dart @@ -1,42 +1,22 @@ import 'package:flutter/material.dart'; +import 'package:prayer_time_app/pages/TasbihFullScreenPage.dart'; +import 'package:provider/provider.dart'; import 'package:vibration/vibration.dart'; import 'package:prayer_time_app/components/custom_app_bar.dart'; +import 'package:prayer_time_app/services/tasbih_provider.dart'; -class TasbihPage extends StatefulWidget { - @override - _TasbihPageState createState() => _TasbihPageState(); -} - -class _TasbihPageState extends State { - int _counter = 0; - int _goal = 33; - - void _incrementCounter() async { - setState(() { - _counter++; - }); - if (await Vibration.hasVibrator() ?? false) { - Vibration.vibrate(duration: 50); - } - if (_counter % _goal == 0) { - if (await Vibration.hasVibrator() ?? false) { - Vibration.vibrate(pattern: [0, 200, 100, 200]); - } - } - } - - void _resetCounter() { - setState(() { - _counter = 0; - }); - } - +class TasbihPage extends StatelessWidget { @override Widget build(BuildContext context) { final isDark = Theme.of(context).brightness == Brightness.dark; + final tasbih = Provider.of(context); return Scaffold( - appBar: customAppBar(context, "Digital Tasbih", back: false), + appBar: customAppBar( + context, + "Digital Tasbih", + back: false, + ), body: Container( width: double.infinity, decoration: BoxDecoration( @@ -52,7 +32,7 @@ class _TasbihPageState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - "Goal: $_goal", + "Goal: ${tasbih.goal}", style: TextStyle( fontSize: 18, color: isDark ? Colors.white70 : Colors.black54, @@ -61,7 +41,7 @@ class _TasbihPageState extends State { ), const SizedBox(height: 20), GestureDetector( - onTap: _incrementCounter, + onTap: tasbih.increment, child: Container( width: 250, height: 250, @@ -82,7 +62,7 @@ class _TasbihPageState extends State { ), child: Center( child: Text( - "$_counter", + "${tasbih.counter}", style: TextStyle( fontSize: 80, fontWeight: FontWeight.bold, @@ -99,7 +79,7 @@ class _TasbihPageState extends State { _buildActionButton( icon: Icons.refresh, label: "Reset", - onPressed: _resetCounter, + onPressed: tasbih.reset, color: Colors.orange, ), const SizedBox(width: 30), @@ -107,10 +87,22 @@ class _TasbihPageState extends State { icon: Icons.settings, label: "Set Goal", onPressed: () { - _showGoalDialog(); + _showGoalDialog(context, tasbih); }, color: Colors.blue, ), + const SizedBox(width: 30), + _buildActionButton( + icon: Icons.fullscreen_rounded, + label: "Fullscreen", + onPressed: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => const TasbihFullScreenPage()), + ); + }, + color: Colors.teal, + ), ], ), ], @@ -136,27 +128,29 @@ class _TasbihPageState extends State { ); } - void _showGoalDialog() { + void _showGoalDialog(BuildContext context, TasbihProvider tasbih) { + int tempGoal = tasbih.goal; + final controller = TextEditingController(text: tasbih.goal.toString()); + showDialog( context: context, builder: (context) { - int tempGoal = _goal; return AlertDialog( title: const Text("Set Tasbih Goal"), content: TextField( + controller: controller, keyboardType: TextInputType.number, + autofocus: true, decoration: const InputDecoration(hintText: "Enter goal (e.g., 33, 100)"), onChanged: (value) { - tempGoal = int.tryParse(value) ?? _goal; + tempGoal = int.tryParse(value) ?? tasbih.goal; }, ), actions: [ TextButton(onPressed: () => Navigator.pop(context), child: const Text("Cancel")), TextButton( onPressed: () { - setState(() { - _goal = tempGoal; - }); + tasbih.setGoal(tempGoal); Navigator.pop(context); }, child: const Text("Set"), diff --git a/lib/services/tasbih_provider.dart b/lib/services/tasbih_provider.dart new file mode 100644 index 0000000..d6bec4a --- /dev/null +++ b/lib/services/tasbih_provider.dart @@ -0,0 +1,59 @@ +import 'package:flutter/foundation.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:vibration/vibration.dart'; + +class TasbihProvider with ChangeNotifier { + int _counter = 0; + int _goal = 33; + bool _notificationsEnabled = true; + + int get counter => _counter; + int get goal => _goal; + + TasbihProvider() { + _loadFromPrefs(); + } + + Future _loadFromPrefs() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + _counter = prefs.getInt('tasbih_counter') ?? 0; + _goal = prefs.getInt('tasbih_goal') ?? 33; + notifyListeners(); + } + + Future _saveToPrefs() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + await prefs.setInt('tasbih_counter', _counter); + await prefs.setInt('tasbih_goal', _goal); + } + + void increment() async { + _counter++; + notifyListeners(); + _saveToPrefs(); + + if (await Vibration.hasVibrator() ?? false) { + Vibration.vibrate(duration: 50); + } + + if (_counter % _goal == 0) { + if (await Vibration.hasVibrator() ?? false) { + Vibration.vibrate(pattern: [0, 200, 100, 200]); + } + } + } + + void reset() { + _counter = 0; + notifyListeners(); + _saveToPrefs(); + } + + void setGoal(int newGoal) { + if (newGoal > 0) { + _goal = newGoal; + notifyListeners(); + _saveToPrefs(); + } + } +}