Download notification created and Profile added in quick links
This commit is contained in:
@@ -13,6 +13,8 @@ import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:open_filex/open_filex.dart';
|
||||
|
||||
import 'package:kmobile/data/models/user.dart';
|
||||
|
||||
@@ -38,13 +40,50 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
||||
List<Transaction> _transactions = [];
|
||||
final _minAmountController = TextEditingController();
|
||||
final _maxAmountController = TextEditingController();
|
||||
//Future<Map<String, dynamic>?>? accountStatementsFuture;
|
||||
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
selectedUser = widget.users[widget.selectedIndex];
|
||||
_loadTransactions();
|
||||
_initializeNotifications();
|
||||
}
|
||||
|
||||
void _initializeNotifications() async {
|
||||
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
||||
|
||||
const AndroidInitializationSettings initializationSettingsAndroid =
|
||||
AndroidInitializationSettings('notification_icon');
|
||||
|
||||
const InitializationSettings initializationSettings =
|
||||
InitializationSettings(android: initializationSettingsAndroid);
|
||||
|
||||
await flutterLocalNotificationsPlugin.initialize(
|
||||
initializationSettings,
|
||||
onDidReceiveNotificationResponse: _onDidReceiveNotificationResponse,
|
||||
);
|
||||
_requestNotificationPermission();
|
||||
}
|
||||
|
||||
void _onDidReceiveNotificationResponse(
|
||||
NotificationResponse notificationResponse) async {
|
||||
final String? payload = notificationResponse.payload;
|
||||
if (payload != null && payload.isNotEmpty) {
|
||||
await OpenFilex.open(payload);
|
||||
}
|
||||
}
|
||||
|
||||
void _requestNotificationPermission() async {
|
||||
if (Platform.isAndroid) {
|
||||
final AndroidFlutterLocalNotificationsPlugin? androidImplementation =
|
||||
flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<
|
||||
AndroidFlutterLocalNotificationsPlugin>();
|
||||
|
||||
if (androidImplementation != null) {
|
||||
await androidImplementation.requestNotificationsPermission();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadTransactions() async {
|
||||
@@ -413,7 +452,6 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
||||
}
|
||||
|
||||
Future<void> _exportToPdf() async {
|
||||
// Step 1: Check if there are any transactions to export.
|
||||
if (_transactions.isEmpty) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
@@ -425,6 +463,27 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
||||
return;
|
||||
}
|
||||
|
||||
// Show downloading notification
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
0,
|
||||
'Downloading PDF',
|
||||
'Your account statement is being downloaded...',
|
||||
const NotificationDetails(
|
||||
android: AndroidNotificationDetails(
|
||||
'download_channel',
|
||||
'Download Notifications',
|
||||
channelDescription:
|
||||
'Notifications for PDF downloads',
|
||||
importance: Importance.low,
|
||||
priority: Priority.low,
|
||||
showProgress: true,
|
||||
maxProgress: 0, // Indeterminate progress
|
||||
ongoing: true,
|
||||
icon: 'notification_icon',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
var logo = await rootBundle.load('assets/images/logo.png');
|
||||
var rubik = await rootBundle.load("assets/fonts/Rubik-Regular.ttf");
|
||||
final pdf = pw.Document();
|
||||
@@ -527,64 +586,81 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
||||
);
|
||||
}));
|
||||
|
||||
//Logic For all platforms
|
||||
try {
|
||||
final Uint8List pdfBytes = await pdf.save();
|
||||
final String timestamp = DateTime.now().millisecondsSinceEpoch.toString();
|
||||
final String fileName = 'account_statement_$timestamp.pdf';
|
||||
|
||||
// For Android
|
||||
if (Platform.isAndroid) {
|
||||
final androidInfo = await DeviceInfoPlugin().androidInfo;
|
||||
if (androidInfo.version.sdkInt < 29) {
|
||||
final status = await Permission.storage.status;
|
||||
if (status.isDenied) {
|
||||
final result = await Permission.storage.request();
|
||||
if (result.isDenied) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Storage permission is required to save PDF'),
|
||||
),
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
String? filePath;
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
final directory = Directory('/storage/emulated/0/Download');
|
||||
if (!await directory.exists()) {
|
||||
await directory.create(recursive: true);
|
||||
}
|
||||
final file = File('${directory.path}/$fileName');
|
||||
await file.writeAsBytes(pdfBytes);
|
||||
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('PDF saved to: ${file.path}'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
// Add for IOS
|
||||
else if (Platform.isIOS) {
|
||||
// On iOS, we save to a temporary directory and then open the share sheet.
|
||||
filePath = file.path;
|
||||
} else if (Platform.isIOS) {
|
||||
final tempDir = await getTemporaryDirectory();
|
||||
final file = await File('${tempDir.path}/$fileName').create();
|
||||
await file.writeAsBytes(pdfBytes);
|
||||
filePath = file.path;
|
||||
} else {
|
||||
// For other platforms, we might just save to temporary directory
|
||||
final tempDir = await getTemporaryDirectory();
|
||||
final file = await File('${tempDir.path}/$fileName').create();
|
||||
await file.writeAsBytes(pdfBytes);
|
||||
filePath = file.path;
|
||||
}
|
||||
|
||||
// Use share_plus to open the iOS share dialog
|
||||
await Share.shareXFiles(
|
||||
[XFile(file.path)],
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Error saving PDF: $e'),
|
||||
// Update notification to download complete
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
0,
|
||||
'PDF Download Complete',
|
||||
'Your account statement has been saved.',
|
||||
const NotificationDetails(
|
||||
android: AndroidNotificationDetails(
|
||||
'download_channel',
|
||||
'Download Notifications',
|
||||
channelDescription:
|
||||
'Notifications for PDF downloads',
|
||||
importance: Importance.high,
|
||||
priority: Priority.high,
|
||||
showProgress: false,
|
||||
ongoing: false,
|
||||
autoCancel: true,
|
||||
icon: 'notification_icon',
|
||||
actions: [
|
||||
AndroidNotificationAction(
|
||||
'open_pdf',
|
||||
'Open PDF',
|
||||
showsUserInterface: true,
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
payload: filePath,
|
||||
);
|
||||
} catch (e) {
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
0,
|
||||
'PDF Download Failed',
|
||||
'Error saving PDF: $e',
|
||||
const NotificationDetails(
|
||||
android: AndroidNotificationDetails(
|
||||
'download_channel',
|
||||
'Download Notifications',
|
||||
channelDescription:
|
||||
'Notifications for PDF downloads',
|
||||
importance: Importance.high,
|
||||
priority: Priority.high,
|
||||
showProgress: false,
|
||||
ongoing: false,
|
||||
icon: 'notification_icon',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -388,6 +388,21 @@ class _DashboardScreenState extends State<DashboardScreen>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final authState = context.read<AuthCubit>().state;
|
||||
String mobileNumberToPass = '';
|
||||
String customerNo = '';
|
||||
String customerName = '';
|
||||
if (authState is Authenticated) {
|
||||
if (selectedAccountIndex >= 0 &&
|
||||
selectedAccountIndex < authState.users.length) {
|
||||
mobileNumberToPass =
|
||||
authState.users[selectedAccountIndex].mobileNo ?? '';
|
||||
customerNo =
|
||||
authState.users[selectedAccountIndex].cifNumber ?? '';
|
||||
customerName =
|
||||
authState.users[selectedAccountIndex].name ?? '';
|
||||
}
|
||||
}
|
||||
return BlocListener<AuthCubit, AuthState>(
|
||||
listener: (context, state) async {
|
||||
if (state is Authenticated && !_biometricPromptShown) {
|
||||
@@ -429,21 +444,7 @@ class _DashboardScreenState extends State<DashboardScreen>
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
onTap: () {
|
||||
final authState = context.read<AuthCubit>().state;
|
||||
String mobileNumberToPass = '';
|
||||
String customerNo = '';
|
||||
String customerName = '';
|
||||
if (authState is Authenticated) {
|
||||
if (selectedAccountIndex >= 0 &&
|
||||
selectedAccountIndex < authState.users.length) {
|
||||
mobileNumberToPass =
|
||||
authState.users[selectedAccountIndex].mobileNo ?? '';
|
||||
customerNo =
|
||||
authState.users[selectedAccountIndex].cifNumber ?? '';
|
||||
customerName =
|
||||
authState.users[selectedAccountIndex].name ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
@@ -677,18 +678,21 @@ class _DashboardScreenState extends State<DashboardScreen>
|
||||
const EnquiryScreen()));
|
||||
}),
|
||||
_buildQuickLink(
|
||||
Symbols.checkbook,
|
||||
AppLocalizations.of(context).chequeManagement,
|
||||
Symbols.person,
|
||||
AppLocalizations.of(context).profile,
|
||||
() {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
const ChequeManagementScreen(),
|
||||
),
|
||||
ProfileScreen(
|
||||
mobileNumber: mobileNumberToPass,
|
||||
customerNo: customerNo,
|
||||
customerName: customerName),
|
||||
),
|
||||
);
|
||||
},
|
||||
disable: true,
|
||||
disable: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user