feat(chat, feed): add images, chat search, likes reply to comment

This commit is contained in:
mso7nueh
2024-08-21 16:24:53 +03:00
parent 892fdbebb8
commit 8349778e48
24 changed files with 2213 additions and 445 deletions

View File

@@ -0,0 +1,116 @@
import 'package:eatvio_app/core/app_export.dart';
import 'package:eatvio_app/features/chat/models/chat_room_preview_model.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class ChatEntryWidget extends StatefulWidget {
final ChatRoom chatRoom;
ChatEntryWidget({
required this.chatRoom,
super.key,
});
@override
State<ChatEntryWidget> createState() => _ChatEntryWidgetState();
}
class _ChatEntryWidgetState extends State<ChatEntryWidget> {
LastMessageClass? lastMessage;
@override
void initState() {
super.initState();
if (widget.chatRoom.lastMessage is Map<String, dynamic>) {
lastMessage = LastMessageClass.fromJson(widget.chatRoom.lastMessage);
}
}
@override
Widget build(BuildContext context) {
return InkWell(
borderRadius: BorderRadius.circular(16),
onTap: () => GoRouter.of(context).pushNamed(
'chatScreen',
extra: widget.chatRoom.id.toString(),
),
child: Ink(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Color(0xFFF6FAFF),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
widget.chatRoom.users.toChatUser.profilePhotoPath == null
? buildAvatarByUsername(widget.chatRoom.users.toChatUser.name)
: CircleAvatar(
radius: 24,
backgroundImage: NetworkImage(
widget.chatRoom.users.toChatUser.profilePhotoUrl,
),
backgroundColor: Colors.white,
),
SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
widget.chatRoom.users.toChatUser.name.length <= 20
? widget.chatRoom.users.toChatUser.name
: widget.chatRoom.users.toChatUser.name.substring(0, 20) + '...',
style: theme.textTheme.titleMedium,
),
Spacer(),
if (lastMessage != null)
Padding(
padding: EdgeInsets.only(left: 8),
child: Text(
lastMessage!.updatedAt.format('dd MMM', 'ru'),
style: theme.textTheme.bodyMedium,
),
),
],
),
SizedBox(height: 8),
if (lastMessage != null)
Text(
lastMessage!.data.toString().trim(),
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: CustomTextStyles.bodyMediumBluegray800,
),
],
),
),
],
),
),
);
}
buildAvatarByUsername(String username) {
return Container(
width: 48,
height: 48,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFFEBF4FF),
shape: BoxShape.circle,
),
child: Text(
username.split(' ').first[0] + username.split(' ')[1][0],
style: TextStyle(
color: Color(0xFF7F9CF5),
fontWeight: FontWeight.w400,
fontSize: 20,
),
),
);
}
}

View File

@@ -0,0 +1,144 @@
import 'package:eatvio_app/core/app_export.dart';
import 'package:flutter/material.dart';
class ChatSearchBarWidget extends StatelessWidget {
ChatSearchBarWidget({
Key? key,
this.alignment,
this.width,
this.scrollPadding,
this.controller,
this.focusNode,
this.autofocus = false,
this.textStyle,
this.textInputType = TextInputType.text,
this.maxLines,
this.hintText,
this.hintStyle,
this.prefix,
this.prefixConstraints,
this.suffix,
this.suffixConstraints,
this.contentPadding,
this.borderDecoration,
this.fillColor,
this.filled = true,
this.validator,
this.onChanged,
}) : super(key: key);
final Alignment? alignment;
final double? width;
final TextEditingController? scrollPadding;
final TextEditingController? controller;
final FocusNode? focusNode;
final bool? autofocus;
final TextStyle? textStyle;
final TextInputType? textInputType;
final int? maxLines;
final String? hintText;
final TextStyle? hintStyle;
final Widget? prefix;
final BoxConstraints? prefixConstraints;
final Widget? suffix;
final BoxConstraints? suffixConstraints;
final EdgeInsets? contentPadding;
final InputBorder? borderDecoration;
final Color? fillColor;
final bool? filled;
final FormFieldValidator<String>? validator;
final Function(String)? onChanged;
@override
Widget build(BuildContext context) {
return searchViewWidget(context);
}
searchViewWidget(BuildContext context) => SizedBox(
width: width ?? double.maxFinite,
child: TextFormField(
controller: controller,
focusNode: focusNode,
onTapOutside: (event) => onTapOutside(),
autofocus: autofocus!,
style: textStyle ?? CustomTextStyles.bodySmallMulishBluegray800,
keyboardType: textInputType,
maxLines: maxLines ?? 1,
decoration: decoration,
validator: validator,
onChanged: (String value) => onChanged?.call(value),
),
);
void onTapOutside() {
if (focusNode != null) {
focusNode?.unfocus();
} else {
FocusManager.instance.primaryFocus?.unfocus();
}
}
InputDecoration get decoration => InputDecoration(
hintText: hintText ?? "",
hintStyle: hintStyle ?? CustomTextStyles.bodySmallMulishBluegray800,
prefixIcon: prefix ??
Padding(
padding: EdgeInsets.only(left: 12),
child: Icon(
Icons.search,
color: Color(0xFF7B8794),
),
),
suffixIcon: suffix ??
IconButton(
onPressed: () => controller!.clear(),
icon: Icon(
Icons.clear,
color: Colors.grey.shade600,
),
),
suffixIconConstraints: suffixConstraints ??
BoxConstraints(
maxHeight: 40.v,
),
isDense: true,
contentPadding: EdgeInsets.all(16),
fillColor: fillColor ?? appTheme.gray100,
filled: filled,
border: borderDecoration ??
OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide.none,
),
enabledBorder: borderDecoration ??
OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide.none,
),
focusedBorder: borderDecoration ??
OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide: BorderSide.none,
),
);
}