Skip to content

Commit 51ff25e

Browse files
committed
feat: added permission request screen
1 parent 49bb285 commit 51ff25e

File tree

7 files changed

+276
-5
lines changed

7 files changed

+276
-5
lines changed

lib/app/modules/onboarding/views/onboarding_page_start_button.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class OnboardingPageStartButton extends StatelessWidget {
1616
child: ElevatedButton(
1717
onPressed: () {
1818
controller.markOnboardingAsCompleted();
19-
Get.offNamed(Routes.HOME);
19+
Get.offNamed(Routes.PERMISSION);
2020
},
2121
style: ElevatedButton.styleFrom(
2222
backgroundColor: TaskWarriorColors.black,
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import 'package:get/get.dart';
2+
3+
import '../controllers/permission_controller.dart';
4+
5+
class PermissionBinding extends Bindings {
6+
@override
7+
void dependencies() {
8+
Get.lazyPut<PermissionController>(
9+
() => PermissionController(),
10+
);
11+
}
12+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import 'package:get/get.dart';
2+
import 'package:permission_handler/permission_handler.dart';
3+
4+
class PermissionController extends GetxController {
5+
final RxBool isStorageGranted = false.obs;
6+
final RxBool isNotificationGranted = false.obs;
7+
final RxBool isLoading = false.obs;
8+
9+
@override
10+
void onInit() {
11+
super.onInit();
12+
checkPermissions();
13+
}
14+
15+
Future<void> checkPermissions() async {
16+
try {
17+
isStorageGranted.value = await Permission.storage.status.isGranted;
18+
isNotificationGranted.value =
19+
await Permission.notification.status.isGranted;
20+
} catch (e) {
21+
print('Error checking permissions: $e');
22+
}
23+
}
24+
25+
Future<void> requestPermissions() async {
26+
try {
27+
isLoading.value = true;
28+
29+
PermissionStatus storageStatus;
30+
if (GetPlatform.isAndroid) {
31+
storageStatus = await Permission.storage.request();
32+
} else {
33+
storageStatus = await Permission.photos.request();
34+
}
35+
isStorageGranted.value = storageStatus.isGranted;
36+
37+
final notificationStatus = await Permission.notification.request();
38+
isNotificationGranted.value = notificationStatus.isGranted;
39+
40+
if (isStorageGranted.value && isNotificationGranted.value) {
41+
Get.offNamed('/home');
42+
}
43+
} catch (e) {
44+
print('Error requesting permissions: $e');
45+
} finally {
46+
isLoading.value = false;
47+
}
48+
}
49+
50+
void openSettings() async {
51+
try {
52+
await Get.offNamed('/home');
53+
} catch (e) {
54+
print('Error opening settings: $e');
55+
}
56+
}
57+
}
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
import 'dart:io';
2+
3+
import 'package:flutter/material.dart';
4+
import 'package:get/get.dart';
5+
import 'package:taskwarrior/app/utils/app_settings/app_settings.dart';
6+
import 'package:taskwarrior/app/utils/constants/taskwarrior_colors.dart';
7+
import '../controllers/permission_controller.dart';
8+
9+
class PermissionView extends GetView<PermissionController> {
10+
const PermissionView({super.key});
11+
12+
@override
13+
Widget build(BuildContext context) {
14+
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
15+
16+
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
17+
WidgetsBinding.instance.addPostFrameCallback((_) {
18+
Get.offAllNamed('/home');
19+
});
20+
return const SizedBox.shrink();
21+
}
22+
23+
return Scaffold(
24+
backgroundColor: isDarkMode
25+
? TaskWarriorColors.kprimaryBackgroundColor
26+
: TaskWarriorColors.kLightPrimaryBackgroundColor,
27+
body: SafeArea(
28+
child: SingleChildScrollView(
29+
child: Padding(
30+
padding: const EdgeInsets.all(24.0),
31+
child: Column(
32+
crossAxisAlignment: CrossAxisAlignment.stretch,
33+
children: [
34+
const SizedBox(height: 24),
35+
Text(
36+
'Why We Need Your Permission',
37+
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
38+
fontWeight: FontWeight.bold,
39+
color: isDarkMode
40+
? TaskWarriorColors.kprimaryTextColor
41+
: TaskWarriorColors.kLightPrimaryTextColor,
42+
),
43+
textAlign: TextAlign.center,
44+
),
45+
const SizedBox(height: 32),
46+
Icon(
47+
Icons.security,
48+
size: 64,
49+
color: AppSettings.isDarkMode
50+
? TaskWarriorColors.black
51+
: TaskWarriorColors.white,
52+
),
53+
const SizedBox(height: 32),
54+
_buildPermissionSection(
55+
context,
56+
icon: Icons.folder_outlined,
57+
title: 'Storage Permission',
58+
description:
59+
'We use storage access to save your tasks, preferences, '
60+
'and app data securely on your device. This ensures that you can '
61+
'pick up where you left off seamlessly, even offline.',
62+
isDarkMode: isDarkMode,
63+
),
64+
const SizedBox(height: 24),
65+
_buildPermissionSection(
66+
context,
67+
icon: Icons.notifications_outlined,
68+
title: 'Notification Permission',
69+
description:
70+
'Notifications keep you updated with important reminders '
71+
'and updates, ensuring you stay on top of your tasks effortlessly.',
72+
isDarkMode: isDarkMode,
73+
),
74+
const SizedBox(height: 24),
75+
Text(
76+
'Your privacy is our top priority. We never access or share your '
77+
'personal files or data without your consent.',
78+
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
79+
color: AppSettings.isDarkMode
80+
? TaskWarriorColors.black
81+
: TaskWarriorColors.white,
82+
),
83+
textAlign: TextAlign.center,
84+
),
85+
const SizedBox(height: 48),
86+
Obx(() => ElevatedButton(
87+
onPressed: controller.isLoading.value
88+
? null
89+
: controller.requestPermissions,
90+
style: ElevatedButton.styleFrom(
91+
padding: const EdgeInsets.all(16),
92+
backgroundColor: AppSettings.isDarkMode
93+
? TaskWarriorColors.black
94+
: TaskWarriorColors.white,
95+
foregroundColor: AppSettings.isDarkMode
96+
? TaskWarriorColors.kprimaryTextColor
97+
: TaskWarriorColors.kLightPrimaryTextColor,
98+
shape: RoundedRectangleBorder(
99+
borderRadius: BorderRadius.circular(12),
100+
),
101+
),
102+
child: controller.isLoading.value
103+
? CircularProgressIndicator(
104+
color: AppSettings.isDarkMode
105+
? TaskWarriorColors.black
106+
: TaskWarriorColors.white,
107+
)
108+
: Text(
109+
'Grant Permissions',
110+
style: TextStyle(
111+
color: AppSettings.isDarkMode
112+
? TaskWarriorColors.kprimaryTextColor
113+
: TaskWarriorColors.kLightPrimaryTextColor,
114+
fontSize: 16,
115+
),
116+
),
117+
)),
118+
const SizedBox(height: 16),
119+
TextButton(
120+
onPressed: () => controller.openSettings(),
121+
style: ButtonStyle(
122+
backgroundColor:
123+
WidgetStateProperty.all(TaskWarriorColors.grey),
124+
),
125+
child: Text(
126+
'You can manage your permissions anytime later in Settings',
127+
style: Theme.of(context).textTheme.bodySmall?.copyWith(
128+
color: AppSettings.isDarkMode
129+
? TaskWarriorColors.black
130+
: TaskWarriorColors.white,
131+
),
132+
textAlign: TextAlign.center,
133+
),
134+
),
135+
const SizedBox(height: 24),
136+
],
137+
),
138+
),
139+
),
140+
),
141+
);
142+
}
143+
144+
Widget _buildPermissionSection(
145+
BuildContext context, {
146+
required IconData icon,
147+
required String title,
148+
required String description,
149+
required bool isDarkMode,
150+
}) {
151+
return Container(
152+
padding: const EdgeInsets.all(16),
153+
decoration: BoxDecoration(
154+
border: Border.all(
155+
color: isDarkMode
156+
? TaskWarriorColors.ksecondaryBackgroundColor
157+
: TaskWarriorColors.borderColor,
158+
),
159+
borderRadius: BorderRadius.circular(12),
160+
color: isDarkMode
161+
? TaskWarriorColors.kdialogBackGroundColor
162+
: TaskWarriorColors.kLightDialogBackGroundColor,
163+
),
164+
child: Column(
165+
crossAxisAlignment: CrossAxisAlignment.start,
166+
children: [
167+
Row(
168+
children: [
169+
Icon(icon, color: TaskWarriorColors.black),
170+
const SizedBox(width: 12),
171+
Expanded(
172+
child: Text(
173+
title,
174+
style: Theme.of(context).textTheme.titleMedium?.copyWith(
175+
fontWeight: FontWeight.bold,
176+
color: isDarkMode
177+
? TaskWarriorColors.kprimaryTextColor
178+
: TaskWarriorColors.kLightPrimaryTextColor,
179+
),
180+
),
181+
),
182+
],
183+
),
184+
const SizedBox(height: 8),
185+
Text(
186+
description,
187+
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
188+
color: isDarkMode
189+
? TaskWarriorColors.ksecondaryTextColor
190+
: TaskWarriorColors.kLightSecondaryTextColor,
191+
),
192+
),
193+
],
194+
),
195+
);
196+
}
197+
}

lib/app/routes/app_pages.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import '../modules/manageTaskServer/bindings/manage_task_server_binding.dart';
1313
import '../modules/manageTaskServer/views/manage_task_server_view.dart';
1414
import '../modules/onboarding/bindings/onboarding_binding.dart';
1515
import '../modules/onboarding/views/onboarding_view.dart';
16+
import '../modules/permission/bindings/permission_binding.dart';
17+
import '../modules/permission/views/permission_view.dart';
1618
import '../modules/profile/bindings/profile_binding.dart';
1719
import '../modules/profile/views/profile_view.dart';
1820
import '../modules/reports/bindings/reports_binding.dart';
@@ -75,5 +77,10 @@ class AppPages {
7577
page: () => const SettingsView(),
7678
binding: SettingsBinding(),
7779
),
80+
GetPage(
81+
name: _Paths.PERMISSION,
82+
page: () => const PermissionView(),
83+
binding: PermissionBinding(),
84+
),
7885
];
7986
}

lib/app/routes/app_routes.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ abstract class Routes {
1414
static const ABOUT = _Paths.ABOUT;
1515
static const REPORTS = _Paths.REPORTS;
1616
static const SETTINGS = _Paths.SETTINGS;
17+
static const PERMISSION = _Paths.PERMISSION;
1718
}
1819

1920
abstract class _Paths {
@@ -27,4 +28,5 @@ abstract class _Paths {
2728
static const ABOUT = '/about';
2829
static const REPORTS = '/reports';
2930
static const SETTINGS = '/settings';
31+
static const PERMISSION = '/permission';
3032
}

lib/main.dart

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
import 'package:flutter/material.dart';
22
import 'package:get/get.dart';
33
import 'package:taskwarrior/app/utils/app_settings/app_settings.dart';
4-
import 'package:taskwarrior/app/utils/permissions/permissions_manager.dart';
54
import 'app/routes/app_pages.dart';
65

76
void main() async {
87
WidgetsFlutterBinding.ensureInitialized();
98
await AppSettings.init();
109

11-
await PermissionsManager.requestAllPermissions();
12-
13-
1410
runApp(
1511
GetMaterialApp(
1612
title: "Application",

0 commit comments

Comments
 (0)