Files
forkmessager/client-mobile/lib/features/chat/presentation/pages/chats_page.dart
T

170 lines
5.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';
import 'package:messenger_app/features/chat/presentation/bloc/chat_bloc.dart';
import 'package:messenger_app/features/chat/presentation/bloc/chat_event.dart';
import 'package:messenger_app/features/chat/presentation/bloc/chat_state.dart';
import 'package:messenger_app/features/auth/presentation/bloc/auth_bloc.dart';
import 'package:messenger_app/features/auth/presentation/bloc/auth_state.dart';
import 'package:messenger_app/features/chat/domain/entities/chat.dart';
import 'package:messenger_app/l10n/app_localizations.dart';
import 'chat_detail_page.dart';
class ChatsPage extends StatefulWidget {
const ChatsPage({super.key});
@override
State<ChatsPage> createState() => _ChatsPageState();
}
class _ChatsPageState extends State<ChatsPage> {
@override
void initState() {
super.initState();
final authState = context.read<AuthBloc>().state;
final userId = authState.maybeWhen(
authenticated: (id) => id,
orElse: () => null,
);
context.read<ChatBloc>().add(ChatEvent.chatsLoaded(currentUserId: userId));
}
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(
title: Text(l10n.chats),
actions: [
IconButton(
icon: const Icon(Icons.bookmark_border),
onPressed: () {
context.read<ChatBloc>().add(const ChatEvent.favoritesRequested());
},
),
],
),
body: BlocConsumer<ChatBloc, ChatState>(
listener: (context, state) {
state.whenOrNull(
chatSelected: (chat, _, __) {
final authState = context.read<AuthBloc>().state;
final userId = authState.maybeWhen(
authenticated: (id) => id,
orElse: () => '',
);
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => ChatDetailPage(
chat: chat,
currentUserId: userId,
),
),
).then((_) {
// Reload chats when returning from detail page
if (context.mounted) {
context.read<ChatBloc>().add(ChatEvent.chatsLoaded(currentUserId: userId));
}
});
},
);
},
builder: (context, state) {
return state.maybeWhen(
loading: (_) => const Center(child: CircularProgressIndicator()),
chatsLoaded: (chats, _) => _buildChatList(chats, l10n),
error: (message, _) => Center(child: Text('${l10n.error}: $message')),
orElse: () => const Center(child: CircularProgressIndicator()),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// TODO: Open contact list to create chat
},
child: const Icon(Icons.edit),
),
);
}
Widget _buildChatList(List<Chat> chats, AppLocalizations l10n) {
if (chats.isEmpty) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.chat_bubble_outline, size: 64, color: Colors.grey),
const SizedBox(height: 16),
Text(l10n.noChats),
const SizedBox(height: 8),
TextButton(
onPressed: () {
final authState = context.read<AuthBloc>().state;
final userId = authState.maybeWhen(
authenticated: (id) => id,
orElse: () => null,
);
context.read<ChatBloc>().add(ChatEvent.chatsLoaded(currentUserId: userId));
},
child: Text(l10n.retry),
),
],
),
);
}
return ListView.separated(
itemCount: chats.length,
separatorBuilder: (context, index) => const Divider(height: 1),
itemBuilder: (context, index) {
final chat = chats[index];
return ListTile(
leading: CircleAvatar(
backgroundImage: chat.avatarUrl != null ? NetworkImage(chat.avatarUrl!) : null,
child: chat.avatarUrl == null
? Text(chat.title.isNotEmpty ? chat.title[0].toUpperCase() : '?')
: null,
),
title: Text(
chat.type == 'favorites' ? l10n.favorites : chat.title,
style: const TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(
chat.lastMessage?.content ?? l10n.noChats,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
trailing: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
if (chat.lastMessageTime != null)
Text(
DateFormat.Hm().format(chat.lastMessageTime!.toLocal()),
style: const TextStyle(fontSize: 12, color: Colors.grey),
),
const SizedBox(height: 4),
if (chat.unreadCount > 0)
Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.circular(10),
),
child: Text(
chat.unreadCount.toString(),
style: const TextStyle(color: Colors.white, fontSize: 10),
),
),
],
),
onTap: () {
context.read<ChatBloc>().add(ChatEvent.chatSelected(chat.id));
},
);
},
);
}
}