178 lines
6.7 KiB
Dart
178 lines
6.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:kmobile/api/services/send_sms_service.dart';
|
|
import 'package:permission_handler/permission_handler.dart';
|
|
import 'package:uuid/uuid.dart';
|
|
|
|
class SmsVerificationHelper {
|
|
final SmsService _smsService = SmsService();
|
|
|
|
Future<void> _showPermanentlyDeniedDialog(BuildContext context) async {
|
|
await showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: const Text("Permission Required"),
|
|
content: const Text(
|
|
"SMS and Phone permissions are required for device verification. Please enable them in your app settings to continue."),
|
|
actions: [
|
|
TextButton(
|
|
child: const Text("Cancel"),
|
|
onPressed: () => Navigator.of(context).pop(),
|
|
),
|
|
TextButton(
|
|
child: const Text("Open Settings"),
|
|
onPressed: () {
|
|
openAppSettings(); // Opens the phone's settings screen for this app
|
|
Navigator.of(context).pop();
|
|
},
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> _showRestrictedSmsDialog(BuildContext context) async {
|
|
await showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: const Text("SMS Permission Restricted"),
|
|
content: const SingleChildScrollView(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"It seems your device is restricting this app from sending SMS messages, which is required for verification. Please follow these steps to enable it:\n"),
|
|
Text("1. Open your device Settings.",
|
|
style: TextStyle(fontWeight: FontWeight.bold)),
|
|
Text("2. Go to 'Apps' or 'Apps & notifications'."),
|
|
Text("3. Find and tap on this app ('KMobile')."),
|
|
Text("4. Tap on the three dots (⋮) in the top right corner."),
|
|
Text(
|
|
"5. Select 'Allow restricted settings' and confirm. This is crucial to allow SMS permission."),
|
|
Text("6. Now you have two options to allow SMS permission:"),
|
|
Text(
|
|
" a. Tap on 'Permissions', then find 'SMS' is set to 'Allow'."),
|
|
Text(
|
|
" b. Alternatively, you can return to the KMobile app, and the SMS permission pop-up should appear again, allowing you to grant it directly."),
|
|
Text(
|
|
"\nSome devices have an additional setting for 'Premium SMS'. If the above doesn't work, look for a 'Premium SMS access' setting (you can search for it in your Settings app) and set it to 'Always Allow' for this app.\n"),
|
|
Text(
|
|
"After you've enabled the permission, please come back to the app."),
|
|
],
|
|
),
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
child: const Text("I've Enabled It"),
|
|
onPressed: () => Navigator.of(context).pop(),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<String?> initiateSmsSequence({
|
|
required BuildContext context,
|
|
}) async {
|
|
bool hasPermission = false;
|
|
|
|
// --- PERMISSION LOOP ---
|
|
while (!hasPermission) {
|
|
// handleSmsPermission will check the status and request if not granted.
|
|
final status = await _smsService.handleSmsPermission();
|
|
|
|
switch (status) {
|
|
case PermissionStatusResult.granted:
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text("Permissions Granted! Proceeding..."),
|
|
duration: Duration(seconds: 2)),
|
|
);
|
|
hasPermission = true; // This will break the loop
|
|
break;
|
|
case PermissionStatusResult.denied:
|
|
// The user denied the permission. We show a dialog to explain why we need it
|
|
// and give them a chance to cancel or let the loop try again.
|
|
final tryAgain = await showDialog<bool>(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: const Text("Permission Required"),
|
|
content: const Text(
|
|
"This app requires SMS and Phone permissions to verify your device. Please grant the permissions to continue."),
|
|
actions: [
|
|
TextButton(
|
|
child: const Text("Cancel"),
|
|
onPressed: () => Navigator.of(context).pop(false),
|
|
),
|
|
TextButton(
|
|
child: const Text("Try Again"),
|
|
onPressed: () => Navigator.of(context).pop(true),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
if (tryAgain != true) {
|
|
return null; // User chose to cancel.
|
|
}
|
|
// If they chose "Try Again", the loop will repeat.
|
|
break;
|
|
case PermissionStatusResult.permanentlyDenied:
|
|
await _showPermanentlyDeniedDialog(context);
|
|
// Give user time to come back from settings
|
|
await Future.delayed(const Duration(seconds: 5));
|
|
// The loop will repeat and re-check the status.
|
|
break;
|
|
case PermissionStatusResult.restricted:
|
|
await _showRestrictedSmsDialog(context);
|
|
// Give user time to come back from settings
|
|
await Future.delayed(const Duration(seconds: 5));
|
|
// The loop will repeat and re-check the status.
|
|
break;
|
|
}
|
|
}
|
|
|
|
// --- SMS SENDING LOOP ---
|
|
// This part will only be reached if hasPermission is true.
|
|
int retries = 3;
|
|
while (retries > 0) {
|
|
var uuid = const Uuid();
|
|
String uniqueId = uuid.v4();
|
|
String smsMessage = uniqueId;
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content:
|
|
Text("Attempting to send verification SMS... (${4 - retries})"),
|
|
duration: const Duration(seconds: 2)),
|
|
);
|
|
|
|
bool isSmsSent = await _smsService.sendVerificationSms(
|
|
context: context,
|
|
destinationNumber: '9580079717', // Replace with your number
|
|
message: smsMessage,
|
|
);
|
|
|
|
if (isSmsSent) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text("SMS sent successfully!"),
|
|
duration: Duration(seconds: 2)),
|
|
);
|
|
return uniqueId;
|
|
} else {
|
|
retries--;
|
|
if (retries > 0) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text("SMS failed to send. Retrying in 5 seconds..."),
|
|
duration: Duration(seconds: 4)),
|
|
);
|
|
await Future.delayed(const Duration(seconds: 5));
|
|
}
|
|
}
|
|
}
|
|
|
|
// If all retries fail
|
|
return null;
|
|
}
|
|
}
|