179 lines
6.7 KiB
Dart
179 lines
6.7 KiB
Dart
import 'package:caller/app/models/contactModels/contactModels.dart';
|
|
import 'package:caller/app/modules/chat/contactModule/contactViews/ContactPage/contactInfo.dart';
|
|
import 'package:caller/app/modules/chat/contactModule/controllers/contactController.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:cached_network_image/cached_network_image.dart';
|
|
class ContactsPage extends StatelessWidget {
|
|
final ScrollController sC = ScrollController();
|
|
final Map<String, GlobalKey> letterKeys = {};
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// Access ContactController
|
|
final contactController = Get.find<ContactController>();
|
|
|
|
return Scaffold(
|
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
|
body: Stack(
|
|
children: [
|
|
Obx(() {
|
|
final totalCount = contactController.functionButtons.length + contactController.contacts.length;
|
|
return ListView.builder(
|
|
controller: sC,
|
|
itemCount: totalCount,
|
|
itemBuilder: (context, index) {
|
|
if (index < contactController.functionButtons.length) {
|
|
// Show function buttons first
|
|
final item = contactController.functionButtons[index];
|
|
return _buildFunctionButton(item,context);
|
|
} else {
|
|
// Show contacts after function buttons
|
|
final contactIndex = index - contactController.functionButtons.length;
|
|
final contact = contactController.contacts[contactIndex];
|
|
|
|
final showHeader = contactIndex == 0 ||
|
|
contact.nameIndex != contactController.contacts[contactIndex - 1].nameIndex;
|
|
|
|
final letterKey = showHeader
|
|
? letterKeys.putIfAbsent(
|
|
contact.nameIndex!,
|
|
() => GlobalKey(),
|
|
)
|
|
: null;
|
|
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
if (showHeader)
|
|
Container(
|
|
key: letterKey,
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 16,
|
|
vertical: 6,
|
|
),
|
|
child: Text(
|
|
contact.nameIndex!,
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
color: Colors.grey[700],
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
color: Theme.of(context).cardColor,
|
|
child: ListTile(
|
|
leading: CircleAvatar(
|
|
radius: 24,
|
|
backgroundImage: CachedNetworkImageProvider(contact.avatarUrl),
|
|
),
|
|
title: Text(
|
|
contact.name,
|
|
style: TextStyle(fontSize: 16),
|
|
),
|
|
subtitle: contact.statusMessage != null
|
|
? Text(contact.statusMessage!)
|
|
: null,
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 2),
|
|
onTap: () {
|
|
Navigator.push(context, MaterialPageRoute(builder: (_)=>ContactInfoPage(contact: contact,)));
|
|
},
|
|
),
|
|
),
|
|
Divider(thickness: 0.3,
|
|
height: 0.1, color: Theme.of(context).dividerColor),
|
|
],
|
|
);
|
|
}
|
|
},
|
|
);
|
|
}),
|
|
Positioned(
|
|
right: 10,
|
|
top: 100,
|
|
bottom: 100,
|
|
width: 24,
|
|
child: _buildIndexBar(context, contactController),
|
|
),
|
|
Obx(() => _buildCurrentLetterIndicator(contactController)),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// Build function button UI
|
|
Widget _buildFunctionButton(ContactItem item,BuildContext context) {
|
|
return Container(
|
|
color: Theme.of(context).cardColor,
|
|
child: ListTile(
|
|
leading: Image.asset(item.avatar, width: 36, height: 36),
|
|
title: Text(item.title.tr),
|
|
onTap: () {},
|
|
),
|
|
);
|
|
}
|
|
|
|
// Index bar on the right side
|
|
Widget _buildIndexBar(BuildContext context, ContactController contactController) {
|
|
return GestureDetector(
|
|
onVerticalDragUpdate: (details) =>
|
|
_handleDrag(details.localPosition.dy, context, contactController),
|
|
onVerticalDragStart: (details) =>
|
|
_handleDrag(details.localPosition.dy, context, contactController),
|
|
onTapDown: (details) =>
|
|
_handleDrag(details.localPosition.dy, context, contactController),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
children: INDEX_BAR_WORDS
|
|
.map(
|
|
(e) => Text(e, style: TextStyle(fontSize: 12, color: Colors.grey)),
|
|
)
|
|
.toList(),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Handle drag events when the user drags on the index bar
|
|
void _handleDrag(
|
|
double localDy,
|
|
BuildContext context,
|
|
ContactController contactController,
|
|
) {
|
|
final box = context.findRenderObject() as RenderBox;
|
|
final tileHeight = box.size.height / INDEX_BAR_WORDS.length;
|
|
final index = (localDy ~/ tileHeight).clamp(0, INDEX_BAR_WORDS.length - 1);
|
|
final letter = INDEX_BAR_WORDS[index];
|
|
contactController.jumpToIndex(letter, sC, letterKeys);
|
|
}
|
|
|
|
// Display current letter indicator when dragging
|
|
Widget _buildCurrentLetterIndicator(ContactController contactController) {
|
|
if (contactController.currentLetter.value.isEmpty) return SizedBox.shrink();
|
|
return Center(
|
|
child: Container(
|
|
width: 80,
|
|
height: 80,
|
|
decoration: BoxDecoration(
|
|
color: Colors.black54,
|
|
borderRadius: BorderRadius.circular(40),
|
|
),
|
|
alignment: Alignment.center,
|
|
child: Text(
|
|
contactController.currentLetter.value,
|
|
style: TextStyle(
|
|
fontSize: 32,
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
// === MOCK INDEX BAR WORDS ===
|
|
const List<String> INDEX_BAR_WORDS = [
|
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
|
];
|