Files
ai_chat_assistant/lib/screens/part_screen.dart
2025-09-17 15:09:05 +08:00

169 lines
5.9 KiB
Dart

import 'package:flutter/material.dart';
import 'dart:ui';
import '../widgets/chat_box.dart';
import '../screens/full_screen.dart';
import 'package:provider/provider.dart';
import '../services/message_service.dart';
import '../widgets/gradient_background.dart';
class PartScreen extends StatefulWidget {
final VoidCallback? onHide;
const PartScreen({super.key, this.onHide});
@override
State<PartScreen> createState() => _PartScreenState();
}
class _PartScreenState extends State<PartScreen> {
final ScrollController _scrollController = ScrollController();
bool _isInitialized = false;
int _lastMessageCount = 0;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
final messageService =
Provider.of<MessageService>(context, listen: false);
messageService.removeNonListeningMessages();
setState(() {
_isInitialized = true;
});
});
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
void _scrollToBottom() {
if (_scrollController.hasClients) {
_scrollController.animateTo(
0.0,
duration: const Duration(milliseconds: 200),
curve: Curves.easeOut,
);
}
}
void _openFullScreen() async {
widget.onHide?.call();
await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const FullScreen(),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
body: LayoutBuilder(
builder: (context, constraints) {
if (!_isInitialized) {
return const SizedBox.shrink();
}
final double minHeight = constraints.maxHeight * 0.16;
final double maxHeight = constraints.maxHeight * 0.4;
final double chatWidth = constraints.maxWidth * 0.94;
return Stack(
children: [
Positioned.fill(
child: IgnorePointer(
ignoring: false,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
final messageService = context.read<MessageService>();
if (widget.onHide != null) widget.onHide!();
setState(() {
_isInitialized = true;
});
messageService.abortReply();
messageService.initializeEmpty();
},
child: Container(
color: Colors.transparent,
),
),
),
),
Padding(
padding: EdgeInsets.only(bottom: constraints.maxHeight * 0.22),
child: Align(
alignment: Alignment.bottomCenter,
child: Consumer<MessageService>(
builder: (context, messageService, child) {
final messageCount = messageService.messages.length;
if (messageCount > _lastMessageCount) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollToBottom();
});
}
_lastMessageCount = messageCount;
return Container(
width: chatWidth,
constraints: BoxConstraints(
minHeight: minHeight,
maxHeight: maxHeight,
),
child: ClipRRect(
borderRadius: BorderRadius.circular(24),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 12, sigmaY: 12),
child: GradientBackground(
colors: const [
Color(0XBF3B0A3F),
Color(0xBF0E0E24),
Color(0xBF0C0B33),
],
borderRadius: BorderRadius.circular(6),
child: Stack(
children: [
Padding(
padding: const EdgeInsets.only(
top: 50, left: 6, right: 6, bottom: 30),
child: LayoutBuilder(
builder: (context, boxConstraints) {
return ChatBox(
scrollController: _scrollController,
messages: messageService.messages,
);
}),
),
Positioned(
top: 6,
right: 6,
child: IconButton(
icon: Image.asset(
'assets/images/open_in_full.png',
width: 24,
height: 24,
package: 'ai_chat_assistant',
),
onPressed: _openFullScreen,
padding: EdgeInsets.zero,
),
),
],
),
),
),
),
);
},
),
),
),
],
);
},
),
);
}
}