feat: DTMF dialpad
All checks were successful
/ mirror (push) Successful in 4s
/ build-stealth (push) Successful in 10m2s
/ build (push) Successful in 10m5s

This commit is contained in:
Florian Griffon 2025-05-07 23:35:47 +03:00
parent dab3fe3790
commit bd3ca98883
3 changed files with 350 additions and 285 deletions

View File

@ -191,6 +191,15 @@ class MainActivity : FlutterActivity() {
result.error("SPEAKER_FAILED", "No active call or failed to set speaker", null)
}
}
"sendDtmfTone" -> {
val digit = call.argument<String>("digit")
if (digit != null) {
val success = MyInCallService.sendDtmfTone(digit)
result.success(success)
} else {
result.error("INVALID_ARGUMENT", "Digit is null", null)
}
}
else -> result.notImplemented()
}
}

View File

@ -52,6 +52,22 @@ class MyInCallService : InCallService() {
}
} ?: false
}
fun sendDtmfTone(digit: String): Boolean {
return instance?.let { service ->
try {
currentCall?.let { call ->
call.playDtmfTone(digit[0])
call.stopDtmfTone()
Log.d(TAG, "Sent DTMF tone: $digit")
true
} ?: false
} catch (e: Exception) {
Log.e(TAG, "Failed to send DTMF tone: $e")
false
}
} ?: false
}
}
private val callCallback = object : Call.Callback() {

View File

@ -1,10 +1,10 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_contacts/flutter_contacts.dart';
import 'package:dialer/services/call_service.dart';
import 'package:dialer/services/obfuscate_service.dart';
import 'package:dialer/widgets/username_color_generator.dart';
import 'package:flutter/services.dart';
class CallPage extends StatefulWidget {
final String displayName;
@ -124,10 +124,32 @@ class _CallPageState extends State<CallPage> {
});
}
void _addDigit(String digit) {
void _addDigit(String digit) async {
print('CallPage: Tapped digit: $digit');
setState(() {
_typedDigits += digit;
});
// Send DTMF tone
const channel = MethodChannel('call_service');
try {
final success =
await channel.invokeMethod<bool>('sendDtmfTone', {'digit': digit});
if (success != true) {
print('CallPage: Failed to send DTMF tone for $digit');
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to send DTMF tone')),
);
}
}
} catch (e) {
print('CallPage: Error sending DTMF tone: $e');
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error sending DTMF tone: $e')),
);
}
}
}
void _toggleMute() async {
@ -195,7 +217,7 @@ class _CallPageState extends State<CallPage> {
print('CallPage: Error hanging up: $e');
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Error hanging up: $e")),
SnackBar(content: Text('Error hanging up: $e')),
);
}
}
@ -227,8 +249,14 @@ class _CallPageState extends State<CallPage> {
print(
'CallPage: Building UI, _callStatus: $_callStatus, route: ${ModalRoute.of(context)?.settings.name ?? "unknown"}');
return PopScope(
canPop:
_callStatus == "Call Ended", // Allow navigation only if call ended
canPop: _callStatus == "Call Ended",
onPopInvoked: (didPop) {
if (!didPop) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Cannot leave during an active call')),
);
}
},
child: Scaffold(
body: Container(
color: Colors.black,
@ -254,8 +282,7 @@ class _CallPageState extends State<CallPage> {
children: [
Icon(
icingProtocolOk ? Icons.lock : Icons.lock_open,
color:
icingProtocolOk ? Colors.green : Colors.red,
color: icingProtocolOk ? Colors.green : Colors.red,
size: 16,
),
const SizedBox(width: 4),
@ -282,12 +309,16 @@ class _CallPageState extends State<CallPage> {
Text(
widget.phoneNumber,
style: TextStyle(
fontSize: statusFontSize, color: Colors.white70),
fontSize: statusFontSize,
color: Colors.white70,
),
),
Text(
_callStatus,
style: TextStyle(
fontSize: statusFontSize, color: Colors.white70),
fontSize: statusFontSize,
color: Colors.white70,
),
),
],
),
@ -298,8 +329,7 @@ class _CallPageState extends State<CallPage> {
if (isKeypadVisible) ...[
const Spacer(flex: 2),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20.0),
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@ -319,20 +349,23 @@ class _CallPageState extends State<CallPage> {
IconButton(
padding: EdgeInsets.zero,
onPressed: _toggleKeypad,
icon: const Icon(Icons.close,
color: Colors.white),
icon: const Icon(
Icons.close,
color: Colors.white,
),
),
],
),
),
Container(
height: MediaQuery.of(context).size.height * 0.35,
height: MediaQuery.of(context).size.height * 0.4,
margin: const EdgeInsets.symmetric(horizontal: 20),
padding: const EdgeInsets.all(8),
child: GridView.count(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
crossAxisCount: 3,
childAspectRatio: 1.3,
childAspectRatio: 1.5,
mainAxisSpacing: 8,
crossAxisSpacing: 8,
children: List.generate(12, (index) {
@ -357,7 +390,9 @@ class _CallPageState extends State<CallPage> {
child: Text(
label,
style: const TextStyle(
fontSize: 32, color: Colors.white),
fontSize: 32,
color: Colors.white,
),
),
),
),
@ -369,8 +404,7 @@ class _CallPageState extends State<CallPage> {
] else ...[
const Spacer(),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 32.0),
padding: const EdgeInsets.symmetric(horizontal: 32.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
@ -395,7 +429,8 @@ class _CallPageState extends State<CallPage> {
isMuted ? 'Unmute' : 'Mute',
style: const TextStyle(
color: Colors.white,
fontSize: 14),
fontSize: 14,
),
),
],
),
@ -414,7 +449,8 @@ class _CallPageState extends State<CallPage> {
'Keypad',
style: TextStyle(
color: Colors.white,
fontSize: 14),
fontSize: 14,
),
),
],
),
@ -437,7 +473,8 @@ class _CallPageState extends State<CallPage> {
'Speaker',
style: TextStyle(
color: Colors.white,
fontSize: 14),
fontSize: 14,
),
),
],
),
@ -464,7 +501,8 @@ class _CallPageState extends State<CallPage> {
'Add Contact',
style: TextStyle(
color: Colors.white,
fontSize: 14),
fontSize: 14,
),
),
],
),
@ -483,7 +521,8 @@ class _CallPageState extends State<CallPage> {
'Change SIM',
style: TextStyle(
color: Colors.white,
fontSize: 14),
fontSize: 14,
),
),
],
),
@ -519,6 +558,7 @@ class _CallPageState extends State<CallPage> {
),
),
),
));
),
);
}
}