Files
Qlyra/lib/frontend/screens/chats/chat_screen.dart
T

257 lines
8.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'dart:ui';
class ChatScreen extends StatefulWidget {
final String name;
final String imageUrl;
const ChatScreen({super.key, required this.name, required this.imageUrl});
@override
State<ChatScreen> createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final TextEditingController _messageController = TextEditingController();
bool _hasText = false;
@override
void initState() {
super.initState();
_messageController.addListener(_onTextChanged);
}
@override
void dispose() {
_messageController.removeListener(_onTextChanged);
_messageController.dispose();
super.dispose();
}
void _onTextChanged() {
final bool newHasText = _messageController.text.trim().isNotEmpty;
if (newHasText != _hasText) {
setState(() {
_hasText = newHasText;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
extendBodyBehindAppBar: true,
appBar: AppBar(
backgroundColor: const Color(0xFF1B1B1B).withOpacity(0.8),
elevation: 0,
surfaceTintColor: Colors.transparent,
leading: IconButton(
icon: const Icon(
Symbols.arrow_back,
color: Colors.white,
weight: 400,
),
onPressed: () => Navigator.pop(context),
),
titleSpacing: 0,
title: Row(
children: [
if (widget.imageUrl.isNotEmpty)
CircleAvatar(
radius: 18,
backgroundImage: NetworkImage(widget.imageUrl),
)
else
CircleAvatar(
radius: 18,
backgroundColor: Colors.blueGrey,
child: Text(
widget.name.isNotEmpty ? widget.name[0].toUpperCase() : '?',
style: const TextStyle(color: Colors.white, fontSize: 12),
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
widget.name,
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600,
fontFamily: 'Outfit',
),
),
],
),
const Text(
'Connecting...',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
fontWeight: FontWeight.w400,
),
),
],
),
),
],
),
actions: [
IconButton(
icon: const Icon(Symbols.call, color: Colors.white, weight: 400),
onPressed: () {},
),
IconButton(
icon: const Icon(
Symbols.more_vert,
color: Colors.white,
weight: 400,
),
onPressed: () {},
),
],
),
body: Stack(
children: [
Positioned.fill(
child: widget.imageUrl.isNotEmpty
? Image.network(
widget.imageUrl,
fit: BoxFit.cover,
opacity: const AlwaysStoppedAnimation(0.4),
)
: Image.network(
'https://images.unsplash.com/photo-1579546929518-9e396f3cc809',
fit: BoxFit.cover,
opacity: const AlwaysStoppedAnimation(0.4),
),
),
const Positioned.fill(
child: DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Colors.transparent, Colors.black87],
),
),
),
),
Column(children: [const Spacer(), _buildInputArea(context)]),
],
),
);
}
Widget _buildInputArea(BuildContext context) {
return SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
curve: Curves.easeOutCubic,
constraints: const BoxConstraints(
minHeight: 54,
maxHeight: 180,
),
decoration: BoxDecoration(
color: const Color(0xFF1B1B1B).withOpacity(0.9),
borderRadius: BorderRadius.circular(28),
border: Border.all(
color: Colors.white.withOpacity(0.1),
width: 0.5,
),
),
padding: const EdgeInsets.symmetric(
horizontal: 14,
vertical: 0,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
Symbols.face,
color: Colors.white.withOpacity(0.7),
size: 24,
weight: 400,
),
const SizedBox(width: 12),
Expanded(
child: TextField(
controller: _messageController,
style: const TextStyle(
color: Colors.white,
fontSize: 16,
),
maxLines: null,
keyboardType: TextInputType.multiline,
textAlignVertical: TextAlignVertical.center,
decoration: const InputDecoration(
hintText: 'Message',
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 16,
),
border: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.zero,
),
),
),
AnimatedContainer(
duration: const Duration(milliseconds: 200),
width: _hasText ? 0 : 36,
child: AnimatedOpacity(
duration: const Duration(milliseconds: 200),
opacity: _hasText ? 0 : 1,
child: _hasText
? const SizedBox.shrink()
: Padding(
padding: const EdgeInsets.only(left: 12),
child: Icon(
Symbols.attachment,
color: Colors.white.withOpacity(0.7),
size: 24,
weight: 400,
),
),
),
),
],
),
),
),
const SizedBox(width: 8),
Container(
width: 54,
height: 54,
alignment: Alignment.center,
decoration: const BoxDecoration(
color: Color(0xFF2B2B2B),
shape: BoxShape.circle,
),
child: Icon(
_hasText ? Symbols.send : Symbols.mic,
color: Colors.white,
size: 24,
weight: 400,
),
),
],
),
),
);
}
}