From d3a0a4740d10eaba318cd56998f05e013819f140 Mon Sep 17 00:00:00 2001 From: AlexisDanlos <91090088+AlexisDanlos@users.noreply.github.com> Date: Sun, 16 Feb 2025 19:19:03 +0100 Subject: [PATCH 1/6] feat: Add CallPage for initiating calls with contact details --- dialer/lib/features/call/call_page.dart | 217 ++++++++++++++++++ .../contacts/widgets/contact_modal.dart | 13 ++ 2 files changed, 230 insertions(+) create mode 100644 dialer/lib/features/call/call_page.dart diff --git a/dialer/lib/features/call/call_page.dart b/dialer/lib/features/call/call_page.dart new file mode 100644 index 0000000..2508556 --- /dev/null +++ b/dialer/lib/features/call/call_page.dart @@ -0,0 +1,217 @@ +import 'dart:typed_data'; +import 'package:flutter/material.dart'; +import 'package:dialer/services/obfuscate_service.dart'; +import 'package:dialer/widgets/username_color_generator.dart'; + +class CallPage extends StatefulWidget { + final String displayName; + final Uint8List? thumbnail; + + const CallPage({super.key, required this.displayName, this.thumbnail}); + + @override + _CallPageState createState() => _CallPageState(); +} + +class _CallPageState extends State { + final ObfuscateService _obfuscateService = ObfuscateService(); + bool isMuted = false; + bool isSpeakerOn = false; + bool isKeypadVisible = false; + bool icingProtocolOk = true; + + void _toggleMute() { + setState(() { + isMuted = !isMuted; + }); + } + + void _toggleSpeaker() { + setState(() { + isSpeakerOn = !isSpeakerOn; + }); + } + + void _toggleKeypad() { + setState(() { + isKeypadVisible = !isKeypadVisible; + }); + } + + void _toggleIcingProtocol() { + setState(() { + icingProtocolOk = !icingProtocolOk; + }); + } + + void _hangUp() { + Navigator.pop(context); + } + + @override + Widget build(BuildContext context) { + final double avatarRadius = isKeypadVisible ? 30.0 : 60.0; + final double nameFontSize = isKeypadVisible ? 20.0 : 32.0; + final double statusFontSize = isKeypadVisible ? 16.0 : 20.0; + + return Scaffold( + body: Container( + color: Colors.black, + child: SafeArea( + child: Column( + children: [ + // Fixed size header area + Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 20), + ObfuscatedAvatar( + imageBytes: widget.thumbnail, + radius: avatarRadius, + backgroundColor: generateColorFromName(widget.displayName), + fallbackInitial: widget.displayName, + ), + const SizedBox(height: 10), + Text( + _obfuscateService.obfuscateData(widget.displayName), + style: TextStyle( + fontSize: nameFontSize, + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 5), + Text( + 'Calling...', + style: TextStyle(fontSize: statusFontSize, color: Colors.white70), + ), + const SizedBox(height: 10), + ], + ), + + // Scrollable middle section + Expanded( + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Keypad if visible + if (isKeypadVisible) + Container( + margin: const EdgeInsets.symmetric(horizontal: 40), + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: Colors.black45, + borderRadius: BorderRadius.circular(10), + ), + child: GridView.count( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + crossAxisCount: 3, + mainAxisSpacing: 10, + crossAxisSpacing: 10, + children: List.generate(12, (index) { + String label; + if (index < 9) { + label = '${index + 1}'; + } else if (index == 9) { + label = '*'; + } else if (index == 10) { + label = '0'; + } else { + label = '#'; + } + return Center( + child: Text( + label, + style: const TextStyle( + fontSize: 24, color: Colors.white), + ), + ); + }), + ), + ), + + // Icing protocol status + GestureDetector( + onTap: _toggleIcingProtocol, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + icingProtocolOk ? Icons.lock : Icons.lock_open, + color: icingProtocolOk ? Colors.green : Colors.red, + ), + const SizedBox(width: 8), + Text( + 'Icing protocol: ${icingProtocolOk ? "ok" : "ko"}', + style: TextStyle( + color: icingProtocolOk ? Colors.green : Colors.red, + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ), + + // Control buttons + Padding( + padding: const EdgeInsets.symmetric(horizontal: 32.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + IconButton( + onPressed: _toggleMute, + icon: Icon( + isMuted ? Icons.mic_off : Icons.mic, + color: Colors.white, + size: 32, + ), + ), + IconButton( + onPressed: _toggleKeypad, + icon: Icon( + Icons.dialpad, + color: isKeypadVisible ? Colors.amber : Colors.white, + size: 32, + ), + ), + IconButton( + onPressed: _toggleSpeaker, + icon: Icon( + isSpeakerOn ? Icons.volume_up : Icons.volume_off, + color: isSpeakerOn ? Colors.amber : Colors.white, + size: 32, + ), + ), + ], + ), + ), + ], + ), + ), + ), + + // Fixed size footer with hang up button + Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: IconButton( + onPressed: _hangUp, + icon: const Icon( + Icons.call_end, + color: Colors.red, + size: 48, + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/dialer/lib/features/contacts/widgets/contact_modal.dart b/dialer/lib/features/contacts/widgets/contact_modal.dart index 632d8be..5d56f7b 100644 --- a/dialer/lib/features/contacts/widgets/contact_modal.dart +++ b/dialer/lib/features/contacts/widgets/contact_modal.dart @@ -5,6 +5,7 @@ import 'package:url_launcher/url_launcher.dart'; import 'package:dialer/widgets/username_color_generator.dart'; import '../../../services/block_service.dart'; import '../../../services/contact_service.dart'; +import '../../../features/call/call_page.dart'; class ContactModal extends StatefulWidget { final Contact contact; @@ -263,6 +264,18 @@ class _ContactModalState extends State { _launchPhoneDialer(phoneNumber); } }, + onLongPress: () { + // Navigate to the beautiful calling page demo + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => CallPage( + displayName: widget.contact.displayName, + thumbnail: widget.contact.thumbnail, + ), + ), + ); + }, ), ListTile( leading: const Icon(Icons.message, color: Colors.blue), -- 2.45.2 From d8180dedb642f73b48b21d882cbf9a81ca42ba60 Mon Sep 17 00:00:00 2001 From: AlexisDanlos <91090088+AlexisDanlos@users.noreply.github.com> Date: Mon, 17 Feb 2025 19:42:07 +0100 Subject: [PATCH 2/6] Updated call page to make it look more like standard dialer call page --- dialer/lib/features/call/call_page.dart | 305 ++++++++++++++++-------- 1 file changed, 206 insertions(+), 99 deletions(-) diff --git a/dialer/lib/features/call/call_page.dart b/dialer/lib/features/call/call_page.dart index 2508556..7d335b5 100644 --- a/dialer/lib/features/call/call_page.dart +++ b/dialer/lib/features/call/call_page.dart @@ -52,7 +52,7 @@ class _CallPageState extends State { Widget build(BuildContext context) { final double avatarRadius = isKeypadVisible ? 30.0 : 60.0; final double nameFontSize = isKeypadVisible ? 20.0 : 32.0; - final double statusFontSize = isKeypadVisible ? 16.0 : 20.0; + final double statusFontSize = isKeypadVisible ? 14.0 : 20.0; return Scaffold( body: Container( @@ -60,17 +60,41 @@ class _CallPageState extends State { child: SafeArea( child: Column( children: [ - // Fixed size header area + // Header area with Icing protocol status first Column( mainAxisSize: MainAxisSize.min, children: [ - const SizedBox(height: 20), + const SizedBox(height: 60), + // Icing protocol status moved here ObfuscatedAvatar( imageBytes: widget.thumbnail, radius: avatarRadius, backgroundColor: generateColorFromName(widget.displayName), fallbackInitial: widget.displayName, ), + const SizedBox(height: 20), + GestureDetector( + onTap: _toggleIcingProtocol, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + icingProtocolOk ? Icons.lock : Icons.lock_open, + color: icingProtocolOk ? Colors.green : Colors.red, + size: 20, + ), + const SizedBox(width: 8), + Text( + 'Icing protocol: ${icingProtocolOk ? "ok" : "ko"}', + style: TextStyle( + color: icingProtocolOk ? Colors.green : Colors.red, + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), const SizedBox(height: 10), Text( _obfuscateService.obfuscateData(widget.displayName), @@ -85,126 +109,209 @@ class _CallPageState extends State { 'Calling...', style: TextStyle(fontSize: statusFontSize, color: Colors.white70), ), - const SizedBox(height: 10), ], ), - // Scrollable middle section + // Middle section with keypad or control buttons Expanded( - child: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - // Keypad if visible - if (isKeypadVisible) - Container( - margin: const EdgeInsets.symmetric(horizontal: 40), - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - color: Colors.black45, - borderRadius: BorderRadius.circular(10), - ), - child: GridView.count( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - crossAxisCount: 3, - mainAxisSpacing: 10, - crossAxisSpacing: 10, - children: List.generate(12, (index) { - String label; - if (index < 9) { - label = '${index + 1}'; - } else if (index == 9) { - label = '*'; - } else if (index == 10) { - label = '0'; - } else { - label = '#'; - } - return Center( - child: Text( - label, - style: const TextStyle( - fontSize: 24, color: Colors.white), - ), - ); - }), - ), - ), + child: Column( + children: [ + // Add a smaller top spacer to move buttons higher + const Spacer(flex: 2), - // Icing protocol status - GestureDetector( - onTap: _toggleIcingProtocol, + if (isKeypadVisible) ...[ + // Close keypad button + Align( + alignment: Alignment.topRight, child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - icingProtocolOk ? Icons.lock : Icons.lock_open, - color: icingProtocolOk ? Colors.green : Colors.red, - ), - const SizedBox(width: 8), - Text( - 'Icing protocol: ${icingProtocolOk ? "ok" : "ko"}', - style: TextStyle( - color: icingProtocolOk ? Colors.green : Colors.red, - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ], + padding: const EdgeInsets.only(right: 20.0), + child: IconButton( + onPressed: _toggleKeypad, + icon: const Icon( + Icons.close, + color: Colors.white, + size: 24, + ), ), ), ), - - // Control buttons + // Keypad + Container( + margin: const EdgeInsets.symmetric(horizontal: 40), + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: Colors.black45, + borderRadius: BorderRadius.circular(10), + ), + child: GridView.count( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + crossAxisCount: 3, + mainAxisSpacing: 10, + crossAxisSpacing: 10, + children: List.generate(12, (index) { + String label; + if (index < 9) { + label = '${index + 1}'; + } else if (index == 9) { + label = '*'; + } else if (index == 10) { + label = '0'; + } else { + label = '#'; + } + return Center( + child: Text( + label, + style: const TextStyle(fontSize: 24, color: Colors.white), + ), + ); + }), + ), + ), + ] else ...[ + // Control buttons row with labels under each button Padding( padding: const EdgeInsets.symmetric(horizontal: 32.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - IconButton( - onPressed: _toggleMute, - icon: Icon( - isMuted ? Icons.mic_off : Icons.mic, - color: Colors.white, - size: 32, - ), + // Mic button with label + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: _toggleMute, + icon: Icon( + isMuted ? Icons.mic_off : Icons.mic, + color: Colors.white, + size: 32, + ), + ), + Text( + isMuted ? 'Unmute' : 'Mute', + style: const TextStyle(color: Colors.white, fontSize: 14), + ), + ], ), - IconButton( - onPressed: _toggleKeypad, - icon: Icon( - Icons.dialpad, - color: isKeypadVisible ? Colors.amber : Colors.white, - size: 32, - ), + // Dialpad button with label + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: _toggleKeypad, + icon: Icon( + Icons.dialpad, + color: Colors.white, + size: 32, + ), + ), + const Text( + 'Keypad', + style: TextStyle(color: Colors.white, fontSize: 14), + ), + ], ), - IconButton( - onPressed: _toggleSpeaker, - icon: Icon( - isSpeakerOn ? Icons.volume_up : Icons.volume_off, - color: isSpeakerOn ? Colors.amber : Colors.white, - size: 32, - ), + // Speaker button with label + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: _toggleSpeaker, + icon: Icon( + isSpeakerOn ? Icons.volume_up : Icons.volume_off, + color: isSpeakerOn ? Colors.amber : Colors.white, + size: 32, + ), + ), + const Text( + 'Speaker', + style: TextStyle(color: Colors.white, fontSize: 14), + ), + ], + ), + ], + ), + ), + + const SizedBox(height: 20), + + // Additional buttons row: "Add Contact" and "Change SIM" + Padding( + padding: const EdgeInsets.symmetric(horizontal: 32.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + // "Add Contact" button + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: () { + // Implement your add contact logic here + }, + icon: const Icon( + Icons.person_add, + color: Colors.white, + size: 32, + ), + ), + const Text( + 'Add Contact', + style: TextStyle(color: Colors.white, fontSize: 14), + ), + ], + ), + // "Change SIM" button + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: () { + // Implement your change SIM logic here + }, + icon: const Icon( + Icons.sim_card, + color: Colors.white, + size: 32, + ), + ), + const Text( + 'Change SIM', + style: TextStyle(color: Colors.white, fontSize: 14), + ), + ], ), ], ), ), ], - ), + + // Add a larger bottom spacer + const Spacer(flex: 6), + ], ), ), - // Fixed size footer with hang up button - Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0), - child: IconButton( - onPressed: _hangUp, - icon: const Icon( - Icons.call_end, - color: Colors.red, - size: 48, + // Hang up button + Transform.translate( + offset: const Offset(0, -40), // Moves button 20 pixels upward + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 10.0), + child: GestureDetector( + onTap: _hangUp, + child: Container( + padding: const EdgeInsets.all(10), // adjust to desired size + decoration: const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + child: const Icon( + Icons.call_end, + color: Colors.white, + size: 40, + ), + ), ), ), ), -- 2.45.2 From 858305d42b269044b09cca6d3b667916045c81ea Mon Sep 17 00:00:00 2001 From: AlexisDanlos <91090088+AlexisDanlos@users.noreply.github.com> Date: Tue, 18 Feb 2025 11:43:48 +0100 Subject: [PATCH 3/6] Add functionality to enhance user experience on the call page --- dialer/lib/features/call/call_page.dart | 380 ++++++++++++------------ 1 file changed, 194 insertions(+), 186 deletions(-) diff --git a/dialer/lib/features/call/call_page.dart b/dialer/lib/features/call/call_page.dart index 7d335b5..e8edf82 100644 --- a/dialer/lib/features/call/call_page.dart +++ b/dialer/lib/features/call/call_page.dart @@ -19,6 +19,13 @@ class _CallPageState extends State { bool isSpeakerOn = false; bool isKeypadVisible = false; bool icingProtocolOk = true; + String _typedDigits = ""; // New state variable for pressed digits + + void _addDigit(String digit) { + setState(() { + _typedDigits += digit; + }); + } void _toggleMute() { setState(() { @@ -50,9 +57,9 @@ class _CallPageState extends State { @override Widget build(BuildContext context) { - final double avatarRadius = isKeypadVisible ? 30.0 : 60.0; - final double nameFontSize = isKeypadVisible ? 20.0 : 32.0; - final double statusFontSize = isKeypadVisible ? 14.0 : 20.0; + final double avatarRadius = isKeypadVisible ? 45.0 : 45.0; // Smaller avatar + final double nameFontSize = isKeypadVisible ? 24.0 : 24.0; // Smaller font + final double statusFontSize = isKeypadVisible ? 16.0 : 16.0; // Smaller status return Scaffold( body: Container( @@ -60,95 +67,103 @@ class _CallPageState extends State { child: SafeArea( child: Column( children: [ - // Header area with Icing protocol status first - Column( - mainAxisSize: MainAxisSize.min, - children: [ - const SizedBox(height: 60), - // Icing protocol status moved here - ObfuscatedAvatar( - imageBytes: widget.thumbnail, - radius: avatarRadius, - backgroundColor: generateColorFromName(widget.displayName), - fallbackInitial: widget.displayName, - ), - const SizedBox(height: 20), - GestureDetector( - onTap: _toggleIcingProtocol, - child: Row( + // Top section - make it more compact + Container( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox(height: 35), + ObfuscatedAvatar( + imageBytes: widget.thumbnail, + radius: avatarRadius, + backgroundColor: generateColorFromName(widget.displayName), + fallbackInitial: widget.displayName, + ), + const SizedBox(height: 4), + Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( icingProtocolOk ? Icons.lock : Icons.lock_open, color: icingProtocolOk ? Colors.green : Colors.red, - size: 20, + size: 16, ), - const SizedBox(width: 8), + const SizedBox(width: 4), Text( 'Icing protocol: ${icingProtocolOk ? "ok" : "ko"}', style: TextStyle( color: icingProtocolOk ? Colors.green : Colors.red, - fontSize: 14, + fontSize: 12, fontWeight: FontWeight.bold, ), ), ], ), - ), - const SizedBox(height: 10), - Text( - _obfuscateService.obfuscateData(widget.displayName), - style: TextStyle( - fontSize: nameFontSize, - color: Colors.white, - fontWeight: FontWeight.bold, + const SizedBox(height: 4), + Text( + _obfuscateService.obfuscateData(widget.displayName), + style: TextStyle( + fontSize: nameFontSize, + color: Colors.white, + fontWeight: FontWeight.bold, + ), ), - ), - const SizedBox(height: 5), - Text( - 'Calling...', - style: TextStyle(fontSize: statusFontSize, color: Colors.white70), - ), - ], + Text( + 'Calling...', + style: TextStyle(fontSize: statusFontSize, color: Colors.white70), + ), + ], + ), ), - // Middle section with keypad or control buttons + // Middle section - make it flexible and scrollable if needed Expanded( child: Column( children: [ - // Add a smaller top spacer to move buttons higher - const Spacer(flex: 2), - if (isKeypadVisible) ...[ - // Close keypad button - Align( - alignment: Alignment.topRight, - child: Padding( - padding: const EdgeInsets.only(right: 20.0), - child: IconButton( - onPressed: _toggleKeypad, - icon: const Icon( - Icons.close, - color: Colors.white, - size: 24, + // Add spacer to push keypad down + const Spacer(flex: 2), + + // Typed digits display + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + _typedDigits, + maxLines: 1, + textAlign: TextAlign.right, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontSize: 24, + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), ), - ), + IconButton( + padding: EdgeInsets.zero, + onPressed: _toggleKeypad, + icon: const Icon(Icons.close, color: Colors.white), + ), + ], ), ), - // Keypad + + // Keypad grid Container( - margin: const EdgeInsets.symmetric(horizontal: 40), - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - color: Colors.black45, - borderRadius: BorderRadius.circular(10), - ), + height: MediaQuery.of(context).size.height * 0.35, + margin: const EdgeInsets.symmetric(horizontal: 20), child: GridView.count( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), crossAxisCount: 3, - mainAxisSpacing: 10, - crossAxisSpacing: 10, + childAspectRatio: 1.3, + mainAxisSpacing: 8, + crossAxisSpacing: 8, children: List.generate(12, (index) { String label; if (index < 9) { @@ -160,157 +175,150 @@ class _CallPageState extends State { } else { label = '#'; } - return Center( - child: Text( - label, - style: const TextStyle(fontSize: 24, color: Colors.white), + return GestureDetector( + onTap: () => _addDigit(label), + child: Container( + decoration: const BoxDecoration( + shape: BoxShape.circle, + color: Colors.transparent, + ), + child: Center( + child: Text( + label, + style: const TextStyle(fontSize: 32, color: Colors.white), + ), + ), ), ); }), ), ), + + // Add spacer after keypad + const Spacer(flex: 1), ] else ...[ - // Control buttons row with labels under each button + const Spacer(), + // Control buttons Padding( padding: const EdgeInsets.symmetric(horizontal: 32.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - // Mic button with label - Column( - mainAxisSize: MainAxisSize.min, + // Main control buttons + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - IconButton( - onPressed: _toggleMute, - icon: Icon( - isMuted ? Icons.mic_off : Icons.mic, - color: Colors.white, - size: 32, - ), + // Mute + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: _toggleMute, + icon: Icon( + isMuted ? Icons.mic_off : Icons.mic, + color: Colors.white, + size: 32, + ), + ), + Text( + isMuted ? 'Unmute' : 'Mute', + style: const TextStyle(color: Colors.white, fontSize: 14), + ), + ], ), - Text( - isMuted ? 'Unmute' : 'Mute', - style: const TextStyle(color: Colors.white, fontSize: 14), + // Keypad + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: _toggleKeypad, + icon: const Icon(Icons.dialpad, color: Colors.white, size: 32), + ), + const Text( + 'Keypad', + style: TextStyle(color: Colors.white, fontSize: 14), + ), + ], + ), + // Speaker + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: _toggleSpeaker, + icon: Icon( + isSpeakerOn ? Icons.volume_up : Icons.volume_off, + color: isSpeakerOn ? Colors.amber : Colors.white, + size: 32, + ), + ), + const Text( + 'Speaker', + style: TextStyle(color: Colors.white, fontSize: 14), + ), + ], ), ], ), - // Dialpad button with label - Column( - mainAxisSize: MainAxisSize.min, + const SizedBox(height: 20), + // Additional buttons + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - IconButton( - onPressed: _toggleKeypad, - icon: Icon( - Icons.dialpad, - color: Colors.white, - size: 32, - ), + // Add Contact + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: () { + // ...existing code... + }, + icon: const Icon(Icons.person_add, color: Colors.white, size: 32), + ), + const Text('Add Contact', + style: TextStyle(color: Colors.white, fontSize: 14)), + ], ), - const Text( - 'Keypad', - style: TextStyle(color: Colors.white, fontSize: 14), - ), - ], - ), - // Speaker button with label - Column( - mainAxisSize: MainAxisSize.min, - children: [ - IconButton( - onPressed: _toggleSpeaker, - icon: Icon( - isSpeakerOn ? Icons.volume_up : Icons.volume_off, - color: isSpeakerOn ? Colors.amber : Colors.white, - size: 32, - ), - ), - const Text( - 'Speaker', - style: TextStyle(color: Colors.white, fontSize: 14), - ), - ], - ), - ], - ), - ), - - const SizedBox(height: 20), - - // Additional buttons row: "Add Contact" and "Change SIM" - Padding( - padding: const EdgeInsets.symmetric(horizontal: 32.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - // "Add Contact" button - Column( - mainAxisSize: MainAxisSize.min, - children: [ - IconButton( - onPressed: () { - // Implement your add contact logic here - }, - icon: const Icon( - Icons.person_add, - color: Colors.white, - size: 32, - ), - ), - const Text( - 'Add Contact', - style: TextStyle(color: Colors.white, fontSize: 14), - ), - ], - ), - // "Change SIM" button - Column( - mainAxisSize: MainAxisSize.min, - children: [ - IconButton( - onPressed: () { - // Implement your change SIM logic here - }, - icon: const Icon( - Icons.sim_card, - color: Colors.white, - size: 32, - ), - ), - const Text( - 'Change SIM', - style: TextStyle(color: Colors.white, fontSize: 14), + // Change SIM + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: () { + // ...existing code... + }, + icon: const Icon(Icons.sim_card, color: Colors.white, size: 32), + ), + const Text('Change SIM', + style: TextStyle(color: Colors.white, fontSize: 14)), + ], ), ], ), ], ), ), + const Spacer(flex: 3), ], - - // Add a larger bottom spacer - const Spacer(flex: 6), ], ), ), - // Hang up button - Transform.translate( - offset: const Offset(0, -40), // Moves button 20 pixels upward - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10.0), - child: GestureDetector( - onTap: _hangUp, - child: Container( - padding: const EdgeInsets.all(10), // adjust to desired size - decoration: const BoxDecoration( - color: Colors.red, - shape: BoxShape.circle, - ), - child: const Icon( - Icons.call_end, - color: Colors.white, - size: 40, - ), + // Bottom section - hang up button + Padding( + padding: const EdgeInsets.only(bottom: 16.0), + child: GestureDetector( + onTap: _hangUp, + child: Container( + padding: const EdgeInsets.all(12), + decoration: const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + child: const Icon( + Icons.call_end, + color: Colors.white, + size: 32, ), ), ), -- 2.45.2 From 09cc07d194555cc1af46c18b1b7a712f50d74ef7 Mon Sep 17 00:00:00 2001 From: alexis Date: Thu, 6 Mar 2025 10:32:36 +0000 Subject: [PATCH 4/6] Actualiser dialer/lib/features/contacts/widgets/contact_modal.dart --- dialer/lib/features/contacts/widgets/contact_modal.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/dialer/lib/features/contacts/widgets/contact_modal.dart b/dialer/lib/features/contacts/widgets/contact_modal.dart index 5d56f7b..c405251 100644 --- a/dialer/lib/features/contacts/widgets/contact_modal.dart +++ b/dialer/lib/features/contacts/widgets/contact_modal.dart @@ -5,6 +5,7 @@ import 'package:url_launcher/url_launcher.dart'; import 'package:dialer/widgets/username_color_generator.dart'; import '../../../services/block_service.dart'; import '../../../services/contact_service.dart'; +import '../../../services/call_service.dart' import '../../../features/call/call_page.dart'; class ContactModal extends StatefulWidget { -- 2.45.2 From 8b4c26f8ae6c84c6586387a5d712ed0e7437bb22 Mon Sep 17 00:00:00 2001 From: alexis Date: Thu, 6 Mar 2025 10:33:59 +0000 Subject: [PATCH 5/6] Actualiser dialer/lib/features/contacts/widgets/contact_modal.dart --- dialer/lib/features/contacts/widgets/contact_modal.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dialer/lib/features/contacts/widgets/contact_modal.dart b/dialer/lib/features/contacts/widgets/contact_modal.dart index c405251..57c1c7c 100644 --- a/dialer/lib/features/contacts/widgets/contact_modal.dart +++ b/dialer/lib/features/contacts/widgets/contact_modal.dart @@ -5,7 +5,7 @@ import 'package:url_launcher/url_launcher.dart'; import 'package:dialer/widgets/username_color_generator.dart'; import '../../../services/block_service.dart'; import '../../../services/contact_service.dart'; -import '../../../services/call_service.dart' +import '../../../services/call_service.dart'; import '../../../features/call/call_page.dart'; class ContactModal extends StatefulWidget { -- 2.45.2 From d59e426bcb0ddb6ce244c56a13427e60f63e401b Mon Sep 17 00:00:00 2001 From: alexis Date: Thu, 6 Mar 2025 10:48:54 +0000 Subject: [PATCH 6/6] Actualiser dialer/lib/features/contacts/widgets/contact_modal.dart --- dialer/lib/features/contacts/widgets/contact_modal.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/dialer/lib/features/contacts/widgets/contact_modal.dart b/dialer/lib/features/contacts/widgets/contact_modal.dart index 57c1c7c..5d56f7b 100644 --- a/dialer/lib/features/contacts/widgets/contact_modal.dart +++ b/dialer/lib/features/contacts/widgets/contact_modal.dart @@ -5,7 +5,6 @@ import 'package:url_launcher/url_launcher.dart'; import 'package:dialer/widgets/username_color_generator.dart'; import '../../../services/block_service.dart'; import '../../../services/contact_service.dart'; -import '../../../services/call_service.dart'; import '../../../features/call/call_page.dart'; class ContactModal extends StatefulWidget { -- 2.45.2