import 'package:flutter/material.dart'; import 'dart:io'; import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; import 'package:tugas_akhir_supabase/screens/community/models/message.dart'; import 'package:flutter/foundation.dart' as foundation; import 'package:tugas_akhir_supabase/core/theme/app_colors.dart'; import 'package:tugas_akhir_supabase/screens/community/components/reply_bar.dart'; class MessageInputWidget extends StatelessWidget { final TextEditingController messageController; final FocusNode focusNode; final bool isUploading; final File? selectedImage; final bool showEmojiKeyboard; final bool isReplying; final Message? replyToMessage; final VoidCallback onSend; final VoidCallback onImageOptions; final VoidCallback onEmojiToggle; final VoidCallback onClearImage; final VoidCallback onCancelReply; final Color themeColor; const MessageInputWidget({ super.key, required this.messageController, required this.focusNode, required this.isUploading, required this.selectedImage, required this.showEmojiKeyboard, required this.isReplying, required this.replyToMessage, required this.onSend, required this.onImageOptions, required this.onEmojiToggle, required this.onClearImage, required this.onCancelReply, required this.themeColor, }); @override Widget build(BuildContext context) { // Wrap everything in a Column to contain emoji keyboard return Column( mainAxisSize: MainAxisSize.min, children: [ // Selected image preview if (selectedImage != null) _buildImagePreview(), // Reply bar if (isReplying) _buildReplyBar(), // Input bar Container( padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 6.0), decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 3, offset: Offset(0, -1), ), ], ), child: SafeArea( top: false, child: Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ // Emoji button IconButton( icon: Icon( showEmojiKeyboard ? Icons.keyboard : Icons.emoji_emotions_outlined, color: themeColor, ), onPressed: onEmojiToggle, padding: EdgeInsets.zero, constraints: BoxConstraints(minWidth: 36, minHeight: 36), ), // Text field Expanded( child: ConstrainedBox( constraints: BoxConstraints( maxHeight: 120.0, // Limit max height ), child: TextField( controller: messageController, focusNode: focusNode, minLines: 1, maxLines: 5, // Allow multiple lines but not too many textCapitalization: TextCapitalization.sentences, decoration: InputDecoration( hintText: 'Ketik pesan...', border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 8.0, vertical: 10.0, ), ), ), ), ), // Attachment button - Make this more visible Container( decoration: BoxDecoration( color: Colors.grey.shade200, borderRadius: BorderRadius.circular(18), ), child: IconButton( icon: Icon( Icons.photo_camera, // Change to camera icon for clarity color: themeColor, ), onPressed: () { // Debug print to verify button is responding print('Image button pressed'); onImageOptions(); }, tooltip: 'Add Image', // Add tooltip padding: EdgeInsets.zero, constraints: BoxConstraints(minWidth: 36, minHeight: 36), ), ), SizedBox(width: 8), // Add spacing // Send button _buildSendButton(), ], ), ), ), // Emoji keyboard - Wrap in AnimatedContainer for smooth transitions AnimatedContainer( duration: Duration(milliseconds: 200), height: showEmojiKeyboard ? _getEmojiKeyboardHeight(context) : 0, child: showEmojiKeyboard ? _buildEmojiPicker(context) : SizedBox(), ), ], ); } Widget _buildImagePreview() { return Container( width: double.infinity, padding: EdgeInsets.all(8.0), color: Colors.grey[200], constraints: BoxConstraints( maxHeight: 200, // Limit maximum height to prevent overflow ), child: Stack( alignment: Alignment.center, children: [ // Image preview with fixed height and width constraints Container( constraints: BoxConstraints(maxHeight: 180, minHeight: 100), width: double.infinity, decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), color: Colors.black, ), child: ClipRRect( borderRadius: BorderRadius.circular(8), child: Image.file( selectedImage!, fit: BoxFit .contain, // Use contain instead of cover to prevent cropping errorBuilder: (context, error, stackTrace) { // Handle image loading errors print('[ERROR] Failed to load image preview: $error'); return Container( height: 100, color: Colors.grey[300], child: Center( child: Icon(Icons.broken_image, color: Colors.grey[600]), ), ); }, ), ), ), // Loading indicator if (isUploading) Container( constraints: BoxConstraints(maxHeight: 180), width: double.infinity, color: Colors.black54, child: Center( child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(Colors.white), ), ), ), // Close button Positioned( top: 0, right: 0, child: Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(20), onTap: onClearImage, child: Container( padding: EdgeInsets.all(4), decoration: BoxDecoration( color: Colors.black54, shape: BoxShape.circle, ), child: Icon(Icons.close, color: Colors.white, size: 20), ), ), ), ), ], ), ); } Widget _buildReplyBar() { if (replyToMessage == null) return SizedBox.shrink(); return ReplyBar(message: replyToMessage!, onCancel: onCancelReply); } Widget _buildSendButton() { final bool canSend = messageController.text.trim().isNotEmpty || selectedImage != null; return GestureDetector( onTap: canSend ? onSend : null, child: Container( width: 36, height: 36, margin: EdgeInsets.only(left: 4, right: 4), decoration: BoxDecoration( color: canSend ? themeColor : Colors.grey, shape: BoxShape.circle, ), child: Icon(Icons.send, color: Colors.white, size: 18), ), ); } Widget _buildEmojiPicker(BuildContext context) { return EmojiPicker( onEmojiSelected: (category, emoji) { messageController.text = messageController.text + emoji.emoji; }, textEditingController: messageController, config: Config(checkPlatformCompatibility: true), ); } // Calculate emoji keyboard height based on screen size and keyboard visibility double _getEmojiKeyboardHeight(BuildContext context) { final screenHeight = MediaQuery.of(context).size.height; final keyboardVisible = MediaQuery.of(context).viewInsets.bottom > 0; // Use smaller height when hardware keyboard is visible return keyboardVisible ? 200 : screenHeight * 0.35; } }