Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lib/components/custom_app_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<Widget>? actions}) {
return AppBar(
title: Text(title),
elevation: 1,
centerTitle: false,
automaticallyImplyLeading: back,
actions: <Widget>[
if (actions != null) ...actions,
IconButton(
icon: Icon(Icons.wb_sunny),
icon: const Icon(Icons.wb_sunny),
onPressed: () => {
currentTheme.switchTheme(),
},
Expand Down
33 changes: 20 additions & 13 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<void> main() async {
Expand Down Expand Up @@ -84,19 +86,24 @@ class _PrayerTimeAppState extends State<PrayerTimeApp> {

@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,
),
);
}
}
140 changes: 140 additions & 0 deletions lib/pages/TasbihFullScreenPage.dart
Original file line number Diff line number Diff line change
@@ -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<TasbihProvider>(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"),
),
],
);
},
);
}
}
76 changes: 35 additions & 41 deletions lib/pages/TasbihPage.dart
Original file line number Diff line number Diff line change
@@ -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<TasbihPage> {
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<TasbihProvider>(context);

return Scaffold(
appBar: customAppBar(context, "Digital Tasbih", back: false),
appBar: customAppBar(
context,
"Digital Tasbih",
back: false,
),
body: Container(
width: double.infinity,
decoration: BoxDecoration(
Expand All @@ -52,7 +32,7 @@ class _TasbihPageState extends State<TasbihPage> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Goal: $_goal",
"Goal: ${tasbih.goal}",
style: TextStyle(
fontSize: 18,
color: isDark ? Colors.white70 : Colors.black54,
Expand All @@ -61,7 +41,7 @@ class _TasbihPageState extends State<TasbihPage> {
),
const SizedBox(height: 20),
GestureDetector(
onTap: _incrementCounter,
onTap: tasbih.increment,
child: Container(
width: 250,
height: 250,
Expand All @@ -82,7 +62,7 @@ class _TasbihPageState extends State<TasbihPage> {
),
child: Center(
child: Text(
"$_counter",
"${tasbih.counter}",
style: TextStyle(
fontSize: 80,
fontWeight: FontWeight.bold,
Expand All @@ -99,18 +79,30 @@ class _TasbihPageState extends State<TasbihPage> {
_buildActionButton(
icon: Icons.refresh,
label: "Reset",
onPressed: _resetCounter,
onPressed: tasbih.reset,
color: Colors.orange,
),
const SizedBox(width: 30),
_buildActionButton(
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,
),
],
),
],
Expand All @@ -136,27 +128,29 @@ class _TasbihPageState extends State<TasbihPage> {
);
}

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"),
Expand Down
Loading
Loading