Download notification created and Profile added in quick links
This commit is contained in:
@@ -34,6 +34,7 @@ android {
|
||||
ndkVersion "27.0.12077973"
|
||||
|
||||
compileOptions {
|
||||
coreLibraryDesugaringEnabled true
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
@@ -80,4 +81,6 @@ flutter {
|
||||
source '../..'
|
||||
}
|
||||
|
||||
dependencies {}
|
||||
dependencies {
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
|
||||
}
|
||||
|
||||
BIN
android/app/src/main/res/drawable/notification_icon.png
Normal file
BIN
android/app/src/main/res/drawable/notification_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
@@ -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,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -6,6 +6,7 @@ import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import device_info_plus
|
||||
import flutter_local_notifications
|
||||
import flutter_secure_storage_macos
|
||||
import local_auth_darwin
|
||||
import package_info_plus
|
||||
@@ -16,6 +17,7 @@ import url_launcher_macos
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
|
||||
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
||||
FLALocalAuthPlugin.register(with: registry.registrar(forPlugin: "FLALocalAuthPlugin"))
|
||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||
|
||||
56
pubspec.lock
56
pubspec.lock
@@ -137,6 +137,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.8"
|
||||
dbus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dbus
|
||||
sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.11"
|
||||
device_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -238,6 +246,38 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
flutter_local_notifications:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_local_notifications
|
||||
sha256: "19ffb0a8bb7407875555e5e98d7343a633bb73707bae6c6a5f37c90014077875"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "19.5.0"
|
||||
flutter_local_notifications_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_linux
|
||||
sha256: e3c277b2daab8e36ac5a6820536668d07e83851aeeb79c446e525a70710770a5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.0"
|
||||
flutter_local_notifications_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_platform_interface
|
||||
sha256: "277d25d960c15674ce78ca97f57d0bae2ee401c844b6ac80fcd972a9c99d09fe"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.1.0"
|
||||
flutter_local_notifications_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_windows
|
||||
sha256: "8d658f0d367c48bd420e7cf2d26655e2d1130147bca1eea917e576ca76668aaf"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
flutter_localizations:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@@ -541,6 +581,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
open_filex:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: open_filex
|
||||
sha256: "9976da61b6a72302cf3b1efbce259200cd40232643a467aac7370addf94d6900"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.7.0"
|
||||
package_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -874,6 +922,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.6"
|
||||
timezone:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timezone
|
||||
sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.10.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -61,6 +61,8 @@ dependencies:
|
||||
device_info_plus: ^11.3.0
|
||||
showcaseview: ^2.0.3
|
||||
package_info_plus: ^4.2.0
|
||||
flutter_local_notifications: ^19.5.0
|
||||
open_filex: ^4.7.0
|
||||
# jailbreak_root_detection: "^1.1.6"
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
flutter_local_notifications_windows
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
||||
Reference in New Issue
Block a user