Commit ebb11608 authored by Sai Srinivas's avatar Sai Srinivas
Browse files

fixes

parent a5ccb211
......@@ -74,6 +74,8 @@ PODS:
- GoogleUtilities/UserDefaults (~> 8.0)
- nanopb (~> 3.30910.0)
- Flutter (1.0.0)
- flutter_contacts (0.0.1):
- Flutter
- flutter_downloader (0.0.1):
- Flutter
- flutter_image_compress_common (1.0.0):
......@@ -212,6 +214,7 @@ DEPENDENCIES:
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
- Flutter (from `Flutter`)
- flutter_contacts (from `.symlinks/plugins/flutter_contacts/ios`)
- flutter_downloader (from `.symlinks/plugins/flutter_downloader/ios`)
- flutter_image_compress_common (from `.symlinks/plugins/flutter_image_compress_common/ios`)
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
......@@ -277,6 +280,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/firebase_messaging/ios"
Flutter:
:path: Flutter
flutter_contacts:
:path: ".symlinks/plugins/flutter_contacts/ios"
flutter_downloader:
:path: ".symlinks/plugins/flutter_downloader/ios"
flutter_image_compress_common:
......@@ -342,6 +347,7 @@ SPEC CHECKSUMS:
FirebaseInstallations: 9980995bdd06ec8081dfb6ab364162bdd64245c3
FirebaseMessaging: 2b9f56aa4ed286e1f0ce2ee1d413aabb8f9f5cb9
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
flutter_contacts: edb1c5ce76aa433e20e6cb14c615f4c0b66e0983
flutter_downloader: b7301ae057deadd4b1650dc7c05375f10ff12c39
flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e
flutter_inappwebview_ios: 8d8d2c6290a3c4787cad303603662fac9a788f75
......
......@@ -15,6 +15,7 @@
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
9AA45C142DD33732002B8BD0 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9AA45C132DD33732002B8BD0 /* GoogleService-Info.plist */; };
9AE33D4D2EB6295300E40DCB /* Contacts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AE33D4C2EB6295200E40DCB /* Contacts.framework */; };
9AED47FD9ED95B95B39F9EF0 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 790ED1546FAD647888E2BE7A /* Pods_RunnerTests.framework */; };
C1A6DB5D3568BFCBCBACC04B /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03FAB6DB27A278FB15FD74E4 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
......@@ -67,6 +68,7 @@
9AA45C132DD33732002B8BD0 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
9AA45C152DD3487F002B8BD0 /* RunnerProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerProfile.entitlements; sourceTree = "<group>"; };
9AA45C162DD3489F002B8BD0 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
9AE33D4C2EB6295200E40DCB /* Contacts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Contacts.framework; path = System/Library/Frameworks/Contacts.framework; sourceTree = SDKROOT; };
B9F0367623E7C0B4F78A4435 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
C968B3C3D5D358B0AFB94F8C /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
......@@ -77,6 +79,7 @@
buildActionMask = 2147483647;
files = (
C1A6DB5D3568BFCBCBACC04B /* Pods_Runner.framework in Frameworks */,
9AE33D4D2EB6295300E40DCB /* Contacts.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -165,6 +168,7 @@
FE7E98E00E75972236D03914 /* Frameworks */ = {
isa = PBXGroup;
children = (
9AE33D4C2EB6295200E40DCB /* Contacts.framework */,
03FAB6DB27A278FB15FD74E4 /* Pods_Runner.framework */,
790ED1546FAD647888E2BE7A /* Pods_RunnerTests.framework */,
);
......
......@@ -2,10 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- here is ok or not this BELOW the URL types section, NOT inside it -->
<key>NSContactsUsageDescription</key>
<string>This app needs access to your contacts to add and view contacts.</string>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
......@@ -62,6 +58,8 @@
<string>This app requires to access your photo library in order to upload image proofs etc.</string>
<key>NSUserNotificationsUsageDescription</key>
<string>This app needs to access notifications.</string>
<key>NSContactsUsageDescription</key>
<string>This app needs access to your contacts to add and view contacts.</string>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>
......
......@@ -11,7 +11,6 @@ import 'package:permission_handler/permission_handler.dart';
import '../../Utils/custom_snackbar.dart';
class ContactListScreen extends StatefulWidget {
const ContactListScreen({super.key});
......@@ -25,11 +24,13 @@ class _ContactListScreenState extends State<ContactListScreen> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
final homeProv = Provider.of<HomescreenNotifier>(context, listen: false);
Future.microtask(() {
final provider = Provider.of<ContactProvider>(context, listen: false);
provider.fetchContactList(homeProv.session, homeProv.empId, 1);
});
});
}
void _addToContact(String name, String phoneNumber) async {
......@@ -47,13 +48,37 @@ class _ContactListScreenState extends State<ContactListScreen> {
context: context,
message: "Opening contact form for $name...",
);
// var permissionStatus = await Permission.contacts.request();
// // Check and request contact permission
// // var permissionStatus = await Permission.contacts.status;
// if (permissionStatus.isDenied) {
// final requestedStatus = await Permission.contacts.request();
// if (!requestedStatus.isGranted) {
// CustomSnackBar.hide(context);
// CustomSnackBar.showError(
// context: context,
// message: "Contact permission is required",
// );
// return;
// }
// }
// if (permissionStatus.isPermanentlyDenied) {
// CustomSnackBar.hide(context);
// _showPermissionDialog();
// return;
// }
// Check current status
var status = await Permission.contacts.status;
// Only request if not already granted
if (!await status.isGranted) {
status = await Permission.contacts.request();
}
// Check and request contact permission
var permissionStatus = await Permission.contacts.status;
if (permissionStatus.isDenied) {
final requestedStatus = await Permission.contacts.request();
if (!requestedStatus.isGranted) {
// Handle denied or permanently denied
if (await status.isDenied) {
CustomSnackBar.hide(context);
CustomSnackBar.showError(
context: context,
......@@ -61,9 +86,8 @@ class _ContactListScreenState extends State<ContactListScreen> {
);
return;
}
}
if (permissionStatus.isPermanentlyDenied) {
if (await status.isPermanentlyDenied) {
CustomSnackBar.hide(context);
_showPermissionDialog();
return;
......@@ -73,7 +97,8 @@ class _ContactListScreenState extends State<ContactListScreen> {
final cleanPhoneNumber = _cleanPhoneNumber(phoneNumber);
// ✅ Instead of inserting contact, open system form
final newContact = Contact()
final newContact =
Contact()
..name = Name(first: name)
..phones = [Phone(cleanPhoneNumber)];
......@@ -88,7 +113,6 @@ class _ContactListScreenState extends State<ContactListScreen> {
context: context,
message: "Contact form opened for $name",
);
} catch (e) {
debugPrint("❌ Error opening contact form: $e");
CustomSnackBar.hide(context);
......@@ -122,10 +146,12 @@ class _ContactListScreenState extends State<ContactListScreen> {
void _showPermissionDialog() {
showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
builder:
(BuildContext context) => AlertDialog(
title: const Text("Permission Required"),
content: const Text(
"Contact permission is permanently denied. Please enable it in app settings to add contacts."),
"Contact permission is permanently denied. Please enable it in app settings to add contacts.",
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
......@@ -182,14 +208,24 @@ class _ContactListScreenState extends State<ContactListScreen> {
onTap: () => Navigator.pop(context, true),
child: SvgPicture.asset(
"assets/svg/appbar_back_button.svg",
height: isSmallScreen ? 22 : isTablet ? 28 : 25,
height:
isSmallScreen
? 22
: isTablet
? 28
: 25,
),
),
const SizedBox(width: 10),
Text(
"Contacts",
style: TextStyle(
fontSize: isSmallScreen ? 16 : isTablet ? 20 : 18,
fontSize:
isSmallScreen
? 16
: isTablet
? 20
: 18,
fontFamily: "Plus Jakarta Sans",
fontWeight: FontWeight.w600,
color: Colors.black87,
......@@ -212,15 +248,19 @@ class _ContactListScreenState extends State<ContactListScreen> {
style: TextStyle(
color: Colors.black54,
fontSize: 16,
fontFamily: "Plus Jakarta Sans"),
fontFamily: "Plus Jakarta Sans",
),
),
);
}
final filteredContacts = provider.contactList
.where((c) => (c.name ?? '')
.toLowerCase()
.contains(_searchController.text.toLowerCase()))
final filteredContacts =
provider.contactList
.where(
(c) => (c.name ?? '').toLowerCase().contains(
_searchController.text.toLowerCase(),
),
)
.toList();
return Padding(
......@@ -251,7 +291,8 @@ class _ContactListScreenState extends State<ContactListScreen> {
itemCount: filteredContacts.length,
itemBuilder: (context, index) {
final contact = filteredContacts[index];
final canSwipe = contact.mobileNumber != null &&
final canSwipe =
contact.mobileNumber != null &&
contact.mobileNumber!.trim().length == 10;
return Padding(
......@@ -259,10 +300,14 @@ class _ContactListScreenState extends State<ContactListScreen> {
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Slidable(
key: Key(contact.mobileNumber?.toString() ?? '${contact.name}_$index'),
key: Key(
contact.mobileNumber?.toString() ??
'${contact.name}_$index',
),
// Left swipe (Add to contact)
startActionPane: canSwipe
startActionPane:
canSwipe
? ActionPane(
motion: const ScrollMotion(),
extentRatio: 0.4, // Width percentage
......@@ -276,8 +321,12 @@ class _ContactListScreenState extends State<ContactListScreen> {
contact.mobileNumber ?? '',
);
},
backgroundColor: const Color(0xFFE5FFE5),
foregroundColor: const Color(0xFF38903c),
backgroundColor: const Color(
0xFFE5FFE5,
),
foregroundColor: const Color(
0xFF38903c,
),
icon: Icons.contact_page,
label: 'Add to Contact',
autoClose: true,
......@@ -287,7 +336,8 @@ class _ContactListScreenState extends State<ContactListScreen> {
: null,
// Right swipe (WhatsApp)
endActionPane: canSwipe
endActionPane:
canSwipe
? ActionPane(
motion: const ScrollMotion(),
extentRatio: 0.4, // Width percentage
......@@ -295,10 +345,16 @@ class _ContactListScreenState extends State<ContactListScreen> {
children: [
SlidableAction(
onPressed: (_) async {
_openWhatsApp(contact.mobileNumber ?? '');
_openWhatsApp(
contact.mobileNumber ?? '',
);
},
backgroundColor: const Color(0xFFE9FFE8),
foregroundColor: const Color(0xFF4CB443),
backgroundColor: const Color(
0xFFE9FFE8,
),
foregroundColor: const Color(
0xFF4CB443,
),
icon: Icons.chat,
label: 'WhatsApp',
autoClose: true,
......@@ -314,7 +370,9 @@ class _ContactListScreenState extends State<ContactListScreen> {
borderRadius: BorderRadius.circular(1),
),
padding: const EdgeInsets.symmetric(
horizontal: 14, vertical: 10),
horizontal: 14,
vertical: 10,
),
child: Row(
children: [
// 👤 Avatar
......@@ -326,23 +384,43 @@ class _ContactListScreenState extends State<ContactListScreen> {
shape: BoxShape.circle,
),
clipBehavior: Clip.antiAlias,
child: (contact.profileImage != null &&
contact.profileImage!.isNotEmpty)
child:
(contact.profileImage != null &&
contact
.profileImage!
.isNotEmpty)
? Image.network(
contact.profileImage!,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return const Icon(Icons.person_outline,
color: Color(0xFF2d2d2d));
errorBuilder: (
context,
error,
stackTrace,
) {
return const Icon(
Icons.person_outline,
color: Color(0xFF2d2d2d),
);
},
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
loadingBuilder: (
context,
child,
loadingProgress,
) {
if (loadingProgress == null)
return child;
return const Center(
child: CircularProgressIndicator(strokeWidth: 2),
child:
CircularProgressIndicator(
strokeWidth: 2,
),
);
},
)
: const Icon(Icons.person_outline, color: Color(0xFF2d2d2d)),
: const Icon(
Icons.person_outline,
color: Color(0xFF2d2d2d),
),
),
const SizedBox(width: 12),
......@@ -350,7 +428,8 @@ class _ContactListScreenState extends State<ContactListScreen> {
// 📝 Info
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
contact.name ?? "-",
......@@ -380,15 +459,25 @@ class _ContactListScreenState extends State<ContactListScreen> {
if (contact.mobileNumber != null &&
contact.mobileNumber!.trim().length == 10)
IconButton(
icon: const Icon(Icons.call, color: Colors.green, size: 24),
icon: const Icon(
Icons.call,
color: Colors.green,
size: 24,
),
onPressed: () async {
final phone = contact.mobileNumber!.trim();
final Uri callUri = Uri(scheme: 'tel', path: phone);
final phone =
contact.mobileNumber!.trim();
final Uri callUri = Uri(
scheme: 'tel',
path: phone,
);
if (await canLaunchUrl(callUri)) {
await launchUrl(callUri);
} else {
debugPrint("❌ Could not launch dialer for $phone");
debugPrint(
"❌ Could not launch dialer for $phone",
);
CustomSnackBar.showError(
context: context,
message: "Unable to open dialer",
......
......@@ -61,10 +61,10 @@ packages:
dependency: transitive
description:
name: async
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
url: "https://pub.dev"
source: hosted
version: "2.12.0"
version: "2.13.0"
auto_size_text:
dependency: "direct main"
description:
......@@ -445,10 +445,10 @@ packages:
dependency: transitive
description:
name: fake_async
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.dev"
source: hosted
version: "1.3.2"
version: "1.3.3"
ffi:
dependency: transitive
description:
......@@ -1188,26 +1188,26 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0"
url: "https://pub.dev"
source: hosted
version: "10.0.8"
version: "11.0.1"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev"
source: hosted
version: "3.0.9"
version: "3.0.10"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
version: "3.0.2"
lints:
dependency: transitive
description:
......@@ -2033,10 +2033,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
url: "https://pub.dev"
source: hosted
version: "14.3.1"
version: "15.0.0"
watcher:
dependency: transitive
description:
......
......@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.107+115
version: 1.0.107+116
environment:
sdk: ^3.7.2
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment