Skip to content

Commit

Permalink
Merge pull request #432 from rohansen856/permission_screen
Browse files Browse the repository at this point in the history
feat: added permission request screen
  • Loading branch information
Pavel401 authored Jan 26, 2025
2 parents 1933da4 + 5434792 commit 94980db
Show file tree
Hide file tree
Showing 9 changed files with 285 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class OnboardingPageStartButton extends StatelessWidget {
child: ElevatedButton(
onPressed: () {
controller.markOnboardingAsCompleted();
Get.offNamed(Routes.HOME);
Get.offNamed(Routes.PERMISSION);
},
style: ElevatedButton.styleFrom(
backgroundColor: TaskWarriorColors.black,
Expand Down
12 changes: 12 additions & 0 deletions lib/app/modules/permission/bindings/permission_binding.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'package:get/get.dart';

import '../controllers/permission_controller.dart';

class PermissionBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut<PermissionController>(
() => PermissionController(),
);
}
}
54 changes: 54 additions & 0 deletions lib/app/modules/permission/controllers/permission_controller.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:taskwarrior/app/utils/permissions/permissions_manager.dart';

class PermissionController extends GetxController {
final RxBool isStorageGranted = false.obs;
final RxBool isNotificationGranted = false.obs;
final RxBool isExteternalStorageGranted = false.obs;
final RxBool isLoading = false.obs;

@override
void onInit() {
super.onInit();
checkPermissions();
}

Future<void> checkPermissions() async {
try {
isStorageGranted.value = await Permission.storage.status.isGranted;
isNotificationGranted.value =
await Permission.notification.status.isGranted;
isExteternalStorageGranted.value =
await Permission.manageExternalStorage.status.isGranted;
} catch (e) {
debugPrint('Error checking permissions: $e');
}
}

Future<void> requestPermissions() async {
try {
isLoading.value = true;

if (!isStorageGranted.value &&
!isNotificationGranted.value &&
!isExteternalStorageGranted.value) {
await PermissionsManager.requestAllPermissions();
}
Get.offNamed('/home');
} catch (e) {
debugPrint('Error requesting permissions: $e');
} finally {
isLoading.value = false;
}
}

void gotoHome() async {
try {
await Get.offNamed('/home');
} catch (e) {
debugPrint('Error opening home screen: $e');
}
}
}
66 changes: 66 additions & 0 deletions lib/app/modules/permission/views/permission_section.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import 'package:flutter/material.dart';
import 'package:taskwarrior/app/utils/constants/taskwarrior_colors.dart';

class PermissionSection extends StatelessWidget {
final IconData icon;
final String title;
final String description;
final bool isDarkMode;

const PermissionSection({
super.key,
required this.icon,
required this.title,
required this.description,
required this.isDarkMode,
});

@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
border: Border.all(
color: isDarkMode
? TaskWarriorColors.ksecondaryBackgroundColor
: TaskWarriorColors.borderColor,
),
borderRadius: BorderRadius.circular(12),
color: isDarkMode
? TaskWarriorColors.kdialogBackGroundColor
: TaskWarriorColors.kLightDialogBackGroundColor,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(icon, color: TaskWarriorColors.black),
const SizedBox(width: 12),
Expanded(
child: Text(
title,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
color: isDarkMode
? TaskWarriorColors.kprimaryTextColor
: TaskWarriorColors.kLightPrimaryTextColor,
),
),
),
],
),
const SizedBox(height: 8),
Text(
description,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: isDarkMode
? TaskWarriorColors.ksecondaryTextColor
: TaskWarriorColors.kLightSecondaryTextColor,
),
),
],
),
);
}
}
142 changes: 142 additions & 0 deletions lib/app/modules/permission/views/permission_view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:taskwarrior/app/modules/permission/views/permission_section.dart';
import 'package:taskwarrior/app/utils/app_settings/app_settings.dart';
import 'package:taskwarrior/app/utils/constants/taskwarrior_colors.dart';
import '../controllers/permission_controller.dart';

class PermissionView extends GetView<PermissionController> {
const PermissionView({super.key});

@override
Widget build(BuildContext context) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark;

if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
WidgetsBinding.instance.addPostFrameCallback((_) {
Get.offAllNamed('/home');
});
return const SizedBox.shrink();
}

return Scaffold(
backgroundColor: isDarkMode
? TaskWarriorColors.kprimaryBackgroundColor
: TaskWarriorColors.kLightPrimaryBackgroundColor,
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 24),
Text(
'Why We Need Your Permission',
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
fontWeight: FontWeight.bold,
color: isDarkMode
? TaskWarriorColors.kprimaryTextColor
: TaskWarriorColors.kLightPrimaryTextColor,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 32),
Icon(
Icons.security,
size: 64,
color: AppSettings.isDarkMode
? TaskWarriorColors.black
: TaskWarriorColors.white,
),
const SizedBox(height: 32),
PermissionSection(
icon: Icons.folder_outlined,
title: 'Storage Permission',
description:
'We use storage access to save your tasks, preferences, '
'and app data securely on your device. This ensures that you can '
'pick up where you left off seamlessly, even offline.',
isDarkMode: isDarkMode,
),
const SizedBox(height: 24),
PermissionSection(
icon: Icons.notifications_outlined,
title: 'Notification Permission',
description:
'Notifications keep you updated with important reminders '
'and updates, ensuring you stay on top of your tasks effortlessly.',
isDarkMode: isDarkMode,
),
const SizedBox(height: 24),
Text(
'Your privacy is our top priority. We never access or share your '
'personal files or data without your consent.',
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: AppSettings.isDarkMode
? TaskWarriorColors.black
: TaskWarriorColors.white,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 48),
Obx(() => ElevatedButton(
onPressed: controller.isLoading.value
? null
: controller.requestPermissions,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(16),
backgroundColor: AppSettings.isDarkMode
? TaskWarriorColors.black
: TaskWarriorColors.white,
foregroundColor: AppSettings.isDarkMode
? TaskWarriorColors.kprimaryTextColor
: TaskWarriorColors.kLightPrimaryTextColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: controller.isLoading.value
? CircularProgressIndicator(
color: AppSettings.isDarkMode
? TaskWarriorColors.black
: TaskWarriorColors.white,
)
: Text(
'Grant Permissions',
style: TextStyle(
color: AppSettings.isDarkMode
? TaskWarriorColors.kprimaryTextColor
: TaskWarriorColors.kLightPrimaryTextColor,
fontSize: 16,
),
),
)),
const SizedBox(height: 16),
TextButton(
onPressed: () => controller.gotoHome(),
style: ButtonStyle(
backgroundColor:
WidgetStateProperty.all(TaskWarriorColors.grey),
),
child: Text(
'You can manage your permissions anytime later in Settings',
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: AppSettings.isDarkMode
? TaskWarriorColors.black
: TaskWarriorColors.white,
),
textAlign: TextAlign.center,
),
),
const SizedBox(height: 24),
],
),
),
),
),
);
}
}
7 changes: 7 additions & 0 deletions lib/app/routes/app_pages.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import '../modules/manageTaskServer/bindings/manage_task_server_binding.dart';
import '../modules/manageTaskServer/views/manage_task_server_view.dart';
import '../modules/onboarding/bindings/onboarding_binding.dart';
import '../modules/onboarding/views/onboarding_view.dart';
import '../modules/permission/bindings/permission_binding.dart';
import '../modules/permission/views/permission_view.dart';
import '../modules/profile/bindings/profile_binding.dart';
import '../modules/profile/views/profile_view.dart';
import '../modules/reports/bindings/reports_binding.dart';
Expand Down Expand Up @@ -75,5 +77,10 @@ class AppPages {
page: () => const SettingsView(),
binding: SettingsBinding(),
),
GetPage(
name: _Paths.PERMISSION,
page: () => const PermissionView(),
binding: PermissionBinding(),
),
];
}
2 changes: 2 additions & 0 deletions lib/app/routes/app_routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ abstract class Routes {
static const ABOUT = _Paths.ABOUT;
static const REPORTS = _Paths.REPORTS;
static const SETTINGS = _Paths.SETTINGS;
static const PERMISSION = _Paths.PERMISSION;
}

abstract class _Paths {
Expand All @@ -27,4 +28,5 @@ abstract class _Paths {
static const ABOUT = '/about';
static const REPORTS = '/reports';
static const SETTINGS = '/settings';
static const PERMISSION = '/permission';
}
4 changes: 0 additions & 4 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:taskwarrior/app/utils/app_settings/app_settings.dart';
import 'package:taskwarrior/app/utils/permissions/permissions_manager.dart';
import 'app/routes/app_pages.dart';

void main() async {
WidgetsFlutterBinding.ensureInitialized();
await AppSettings.init();

await PermissionsManager.requestAllPermissions();


runApp(
GetMaterialApp(
title: "Application",
Expand Down
2 changes: 1 addition & 1 deletion test/routes/app_pages_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void main() {
test('All routes should be defined correctly', () {
final routes = AppPages.routes;

expect(routes.length, 9);
expect(routes.length, 10);

expect(
routes.any((route) =>
Expand Down

0 comments on commit 94980db

Please sign in to comment.