feat: Implement About Us and Agent Home screens, update routing, and add new assets and plugins.

This commit is contained in:
pradeepkumar
2026-03-08 12:15:15 +05:30
parent 219acfc013
commit b4d22df8ba
17 changed files with 2795 additions and 112 deletions

View File

@@ -63,15 +63,15 @@ class _ConversationsScreenState extends ConsumerState<ConversationsScreen> {
// -- Header with back arrow, search, icons --
Widget _buildHeader() {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
padding: const EdgeInsets.fromLTRB(16, 8, 16, 12),
child: Container(
height: 51,
height: 48,
decoration: BoxDecoration(
border: Border.all(
color: AppColors.primaryDark,
width: 0.5,
color: AppColors.primaryDark.withValues(alpha: 0.2),
width: 1,
),
borderRadius: BorderRadius.circular(7),
borderRadius: BorderRadius.circular(15),
),
child: Row(
children: [
@@ -88,11 +88,11 @@ class _ConversationsScreenState extends ConsumerState<ConversationsScreen> {
}
},
behavior: HitTestBehavior.opaque,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 14),
child: Icon(
Icons.arrow_back_ios_new,
size: 17,
size: 16,
color: AppColors.primaryDark,
),
),
@@ -106,7 +106,7 @@ class _ConversationsScreenState extends ConsumerState<ConversationsScreen> {
style: const TextStyle(
fontFamily: 'Fractul',
fontSize: 15,
fontWeight: FontWeight.w700,
fontWeight: FontWeight.w600,
color: AppColors.primaryDark,
),
decoration: const InputDecoration(
@@ -114,7 +114,7 @@ class _ConversationsScreenState extends ConsumerState<ConversationsScreen> {
hintStyle: TextStyle(
fontFamily: 'Fractul',
fontSize: 15,
fontWeight: FontWeight.w700,
fontWeight: FontWeight.w600,
color: AppColors.hintText,
),
border: InputBorder.none,
@@ -129,7 +129,7 @@ class _ConversationsScreenState extends ConsumerState<ConversationsScreen> {
style: TextStyle(
fontFamily: 'Fractul',
fontSize: 15,
fontWeight: FontWeight.w700,
fontWeight: FontWeight.w600,
color: AppColors.primaryDark,
),
),
@@ -139,11 +139,11 @@ class _ConversationsScreenState extends ConsumerState<ConversationsScreen> {
GestureDetector(
onTap: () => setState(() => _isSearchActive = true),
behavior: HitTestBehavior.opaque,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Icon(
Icons.search,
size: 20,
size: 22,
color: AppColors.primaryDark,
),
),
@@ -152,11 +152,11 @@ class _ConversationsScreenState extends ConsumerState<ConversationsScreen> {
GestureDetector(
onTap: () {},
behavior: HitTestBehavior.opaque,
child: Padding(
padding: const EdgeInsets.only(right: 12, left: 4),
child: const Padding(
padding: EdgeInsets.only(right: 14, left: 2),
child: Icon(
Icons.more_horiz,
size: 20,
size: 22,
color: AppColors.primaryDark,
),
),
@@ -173,7 +173,7 @@ class _ConversationsScreenState extends ConsumerState<ConversationsScreen> {
baseColor: const Color(0xFFE8E8E8),
highlightColor: const Color(0xFFF5F5F5),
child: ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 12),
padding: const EdgeInsets.symmetric(horizontal: 16),
physics: const NeverScrollableScrollPhysics(),
itemCount: 6,
itemBuilder: (_, index) => Padding(
@@ -181,14 +181,14 @@ class _ConversationsScreenState extends ConsumerState<ConversationsScreen> {
child: Row(
children: [
Container(
width: 52,
height: 52,
width: 56,
height: 56,
decoration: const BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
),
const SizedBox(width: 10),
const SizedBox(width: 14),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -215,7 +215,7 @@ class _ConversationsScreenState extends ConsumerState<ConversationsScreen> {
),
const SizedBox(width: 8),
Container(
width: 45,
width: 55,
height: 12,
decoration: BoxDecoration(
color: Colors.white,
@@ -303,10 +303,13 @@ class _ConversationsScreenState extends ConsumerState<ConversationsScreen> {
child: ListView.separated(
padding: EdgeInsets.zero,
itemCount: filtered.length,
separatorBuilder: (_, __) => Divider(
color: AppColors.primaryDark.withValues(alpha: 0.1),
height: 0.5,
thickness: 0.5,
separatorBuilder: (context, index) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Divider(
color: AppColors.primaryDark.withValues(alpha: 0.1),
height: 1,
thickness: 1,
),
),
itemBuilder: (context, index) {
return _ConversationTile(
@@ -318,7 +321,6 @@ class _ConversationsScreenState extends ConsumerState<ConversationsScreen> {
),
);
}
}
// -- Conversation Tile Widget --
@@ -350,6 +352,7 @@ class _ConversationTile extends StatelessWidget {
final avatarUrl = _resolveAvatarUrl(otherParty.avatar);
final lastMessage = conversation.lastMessageText ?? '';
final timestamp = _formatTimestamp(conversation.lastMessageAt);
final unread = conversation.unreadCount;
final firstLetter = otherParty.name.isNotEmpty
? otherParty.name[0].toUpperCase()
: '?';
@@ -357,32 +360,45 @@ class _ConversationTile extends StatelessWidget {
return InkWell(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// Avatar with online indicator
Stack(
children: [
ClipOval(
child: avatarUrl.isNotEmpty
? CachedNetworkImage(
imageUrl: avatarUrl,
width: 52,
height: 52,
fit: BoxFit.cover,
placeholder: (_, url) => _AvatarFallback(
letter: firstLetter,
),
errorWidget: (_, url, err) => _AvatarFallback(
letter: firstLetter,
),
)
: _AvatarFallback(letter: firstLetter),
Container(
width: 56,
height: 56,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: AppColors.primaryDark.withValues(alpha: 0.15),
width: 1.5,
),
),
child: ClipOval(
child: avatarUrl.isNotEmpty
? CachedNetworkImage(
imageUrl: avatarUrl,
width: 56,
height: 56,
fit: BoxFit.cover,
placeholder: (context, url) => _AvatarFallback(
letter: firstLetter,
),
errorWidget: (context, url, err) =>
_AvatarFallback(
letter: firstLetter,
),
)
: _AvatarFallback(letter: firstLetter),
),
),
if (otherParty.isOnline)
Positioned(
right: 0,
bottom: 0,
right: 1,
bottom: 1,
child: Container(
width: 14,
height: 14,
@@ -398,31 +414,61 @@ class _ConversationTile extends StatelessWidget {
),
],
),
const SizedBox(width: 10),
const SizedBox(width: 14),
// Name and last message
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
otherParty.name,
style: const TextStyle(
fontFamily: 'Fractul',
fontSize: 14,
fontWeight: FontWeight.w700,
color: AppColors.primaryDark,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
// Name row with optional unread badge
Row(
children: [
Expanded(
child: Text(
otherParty.name,
style: TextStyle(
fontFamily: 'Fractul',
fontSize: 14,
fontWeight:
unread > 0 ? FontWeight.w700 : FontWeight.w600,
color: AppColors.primaryDark,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
if (unread > 0) ...[
const SizedBox(width: 8),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 7, vertical: 2),
decoration: BoxDecoration(
color: AppColors.accentOrange,
borderRadius: BorderRadius.circular(10),
),
child: Text(
'$unread',
style: const TextStyle(
fontFamily: 'Fractul',
fontSize: 11,
fontWeight: FontWeight.w700,
color: Colors.white,
),
),
),
],
],
),
const SizedBox(height: 4),
Text(
lastMessage,
style: const TextStyle(
style: TextStyle(
fontFamily: 'SourceSerif4',
fontSize: 14,
fontSize: 13,
fontWeight: FontWeight.w400,
color: AppColors.primaryDark,
color: unread > 0
? AppColors.primaryDark
: AppColors.hintText,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
@@ -430,15 +476,17 @@ class _ConversationTile extends StatelessWidget {
],
),
),
const SizedBox(width: 8),
const SizedBox(width: 10),
// Timestamp
Text(
timestamp,
style: const TextStyle(
style: TextStyle(
fontFamily: 'SourceSerif4',
fontSize: 14,
fontSize: 13,
fontWeight: FontWeight.w400,
color: AppColors.primaryDark,
color: unread > 0
? AppColors.primaryDark
: AppColors.hintText,
),
),
],
@@ -458,8 +506,8 @@ class _AvatarFallback extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 52,
height: 52,
width: 56,
height: 56,
decoration: const BoxDecoration(
color: Color(0xFFE8E8E8),
shape: BoxShape.circle,
@@ -469,7 +517,7 @@ class _AvatarFallback extends StatelessWidget {
letter,
style: const TextStyle(
fontFamily: 'Fractul',
fontSize: 20,
fontSize: 22,
fontWeight: FontWeight.w700,
color: AppColors.primaryDark,
),
@@ -497,7 +545,7 @@ String _formatTimestamp(String? isoTimestamp) {
return 'Now';
}
// Same day: show time like "2 hours Ago"
// Same day: show relative time
if (messageDate == today) {
if (diff.inHours >= 1) {
return '${diff.inHours} hour${diff.inHours > 1 ? 's' : ''} Ago';