Skip to content

Commit

Permalink
TW-503: Update UI chat details for responsive mobile, tablet, web
Browse files Browse the repository at this point in the history
  • Loading branch information
nqhhdev authored and hoangdat committed Sep 7, 2023
1 parent 6cd1f04 commit 07fe67e
Show file tree
Hide file tree
Showing 9 changed files with 497 additions and 431 deletions.
16 changes: 15 additions & 1 deletion assets/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2686,5 +2686,19 @@
"select" : "Select",
"copyMessageText" : "Copy message text",
"pinMessage" : "Pin message",
"add": "Add"
"add": "Add",
"addMembers": "Add members",
"chatInfo": "Chat info",
"mute": "Mute",
"membersInfo": "Members ({count})",
"@membersInfo": {
"placeholders": {
"count": {}
}
},
"members": "Members",
"media": "Media",
"files": "Files",
"links": "Links",
"downloads": "Downloads"
}
91 changes: 83 additions & 8 deletions lib/pages/chat_details/chat_details.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import 'package:collection/collection.dart';
import 'package:file_picker/file_picker.dart';
import 'package:fluffychat/di/global/get_it_initializer.dart';
import 'package:fluffychat/pages/chat_details/chat_details_actions_enum.dart';
import 'package:fluffychat/pages/chat_details/chat_details_page_view/chat_details_members_page.dart';
import 'package:fluffychat/pages/chat_details/chat_details_page_view/chat_details_page_enum.dart';
import 'package:fluffychat/pages/invitation_selection/invitation_selection.dart';
import 'package:fluffychat/pages/invitation_selection/invitation_selection_web.dart';
import 'package:fluffychat/presentation/extensions/room_summary_extension.dart';
import 'package:fluffychat/presentation/model/chat_details/chat_details_page_model.dart';
import 'package:fluffychat/utils/extension/build_context_extension.dart';
import 'package:fluffychat/utils/responsive/responsive_utils.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -33,20 +39,38 @@ class ChatDetails extends StatefulWidget {
}

class ChatDetailsController extends State<ChatDetails> {
static const invitationSelectionMobileAndTabletKey =
Key('InvitationSelectionMobileAndTabletKey');
final invitationSelectionMobileAndTabletKey =
const Key('InvitationSelectionMobileAndTabletKey');

static const invitationSelectionWebAndDesktopKey =
Key('InvitationSelectionWebAndDesktopKey');
final invitationSelectionWebAndDesktopKey =
const Key('InvitationSelectionWebAndDesktopKey');

final actionsMobileAndTabletKey = const Key('ActionsMobileAndTabletKey');

final actionsWebAndDesktopKey = const Key('ActionsWebAndDesktopKey');

final responsive = getIt.get<ResponsiveUtils>();

PageController pageController = PageController();

final ValueNotifier<int> currentPage = ValueNotifier(0);

List<User>? members;

bool displaySettings = false;

String? get roomId => widget.roomId;

bool get isMobileAndTablet =>
responsive.isMobile(context) || responsive.isTablet(context);

Room? get room => Matrix.of(context).client.getRoomById(roomId!);

int get actualMembersCount => room!.summary.actualMembersCount;

void toggleDisplaySettings() =>
setState(() => displaySettings = !displaySettings);

String? get roomId => widget.roomId;

void setDisplaynameAction() async {
final room = Matrix.of(context).client.getRoomById(roomId!)!;
final input = await showTextInputDialog(
Expand Down Expand Up @@ -366,21 +390,23 @@ class ChatDetailsController extends State<ChatDetails> {
showDialog(
context: context,
barrierDismissible: false,
useSafeArea: false,
useRootNavigator: PlatformInfos.isMobile ? false : true,
builder: (context) {
return SlotLayout(
config: <Breakpoint, SlotLayoutConfig>{
const WidthPlatformBreakpoint(
begin: ResponsiveUtils.minDesktopWidth,
): SlotLayout.from(
key: invitationSelectionMobileAndTabletKey,
key: invitationSelectionWebAndDesktopKey,
builder: (_) => InvitationSelectionWebView(
roomId: roomId!,
),
),
const WidthPlatformBreakpoint(
end: ResponsiveUtils.minDesktopWidth,
): SlotLayout.from(
key: invitationSelectionWebAndDesktopKey,
key: invitationSelectionMobileAndTabletKey,
builder: (_) => InvitationSelection(
roomId: roomId!,
),
Expand All @@ -391,6 +417,55 @@ class ChatDetailsController extends State<ChatDetails> {
);
}

List<ChatDetailsActions> chatDetailsActionsButton() => [
if (responsive.isDesktop(context)) ChatDetailsActions.addMembers,
ChatDetailsActions.mute,
ChatDetailsActions.search,
ChatDetailsActions.more,
];

List<ChatDetailsPageModel> chatDetailsPages() => [
ChatDetailsPageModel(
page: ChatDetailsPage.members,
child: ChatDetailsMembersPage(
members: members ?? [],
actualMembersCount: actualMembersCount,
canRequestMoreMembers: members!.length < actualMembersCount,
requestMoreMembersAction: requestMoreMembersAction,
openDialogInvite: openDialogInvite,
isMobileAndTablet: isMobileAndTablet,
),
),
const ChatDetailsPageModel(
page: ChatDetailsPage.media,
child: SizedBox.shrink(),
),
const ChatDetailsPageModel(
page: ChatDetailsPage.files,
child: SizedBox.shrink(),
),
const ChatDetailsPageModel(
page: ChatDetailsPage.links,
child: SizedBox.shrink(),
),
const ChatDetailsPageModel(
page: ChatDetailsPage.downloads,
child: SizedBox.shrink(),
),
];

void onTapActionsButton(ChatDetailsActions action) {
switch (action) {
case ChatDetailsActions.addMembers:
openDialogInvite();
break;
case ChatDetailsActions.mute:
case ChatDetailsActions.search:
case ChatDetailsActions.more:
break;
}
}

@override
Widget build(BuildContext context) {
members ??=
Expand Down
31 changes: 16 additions & 15 deletions lib/pages/chat_details/chat_details_actions_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,23 @@ class ChatDetailsActionsButton extends StatelessWidget {
Widget build(BuildContext context) {
return Material(
color: Colors.transparent,
child: Container(
width: width,
padding: padding ?? const EdgeInsetsDirectional.all(8),
decoration: ShapeDecoration(
color: buttonColor,
shape: RoundedRectangleBorder(
side: borderSide ??
BorderSide(
width: 0.50,
color: LinagoraRefColors.material().neutral[90]!,
),
borderRadius: BorderRadius.circular(borderRadius ?? 16),
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(borderRadius ?? 16),
child: Container(
width: width,
padding: padding ?? const EdgeInsetsDirectional.all(8),
decoration: ShapeDecoration(
color: buttonColor,
shape: RoundedRectangleBorder(
side: borderSide ??
BorderSide(
width: 0.50,
color: LinagoraRefColors.material().neutral[90]!,
),
borderRadius: BorderRadius.circular(borderRadius ?? 16),
),
),
),
child: InkWell(
onTap: onTap,
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Expand Down
63 changes: 63 additions & 0 deletions lib/pages/chat_details/chat_details_header_view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import 'package:fluffychat/pages/chat_details/chat_details_actions_enum.dart';
import 'package:flutter/material.dart';

import 'chat_details_actions_button.dart';

typedef OnTapIconButtonCallbackAction = Function(ChatDetailsActions);

class ActionsHeaderBuilder extends StatelessWidget {
final List<ChatDetailsActions> actions;

final double? width;

final double? iconSize;

final double? borderRadius;

final BorderSide? borderSide;

final EdgeInsetsDirectional? padding;

final Color? buttonColor;

final Color? iconColor;

final OnTapIconButtonCallbackAction? onTap;

const ActionsHeaderBuilder({
super.key,
required this.actions,
this.width,
this.iconSize,
this.borderRadius,
this.borderSide,
this.padding,
this.buttonColor,
this.iconColor,
this.onTap,
});

@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsetsDirectional.all(16.0),
child: Wrap(
spacing: 16,
children: actions.map((action) {
return ChatDetailsActionsButton(
title: action.getTitle(context),
onTap: () => onTap!(action),
iconData: action.getIconData(),
iconSize: iconSize,
width: width,
borderRadius: borderRadius,
borderSide: borderSide,
padding: padding,
buttonColor: buttonColor,
iconColor: iconColor,
);
}).toList(),
),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import 'package:fluffychat/pages/chat_details/participant_list_item.dart';
import 'package:flutter/material.dart';
import 'package:linagora_design_flutter/linagora_design_flutter.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:matrix/matrix.dart';

class ChatDetailsMembersPage extends StatelessWidget {
final List<User> members;
final int actualMembersCount;
final VoidCallback openDialogInvite;
final VoidCallback requestMoreMembersAction;
final bool canRequestMoreMembers;
final bool isMobileAndTablet;

const ChatDetailsMembersPage({
super.key,
required this.members,
required this.actualMembersCount,
required this.openDialogInvite,
required this.requestMoreMembersAction,
required this.canRequestMoreMembers,
required this.isMobileAndTablet,
});

@override
Widget build(BuildContext context) {
return Column(
children: [
_listMemberInfoMobileAndTablet(context),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: members.length + (canRequestMoreMembers ? 1 : 0),
itemBuilder: (BuildContext context, int index) {
if (index < members.length) {
return ParticipantListItem(members[index]);
}

return ListTile(
title: Text(
L10n.of(context)!.loadCountMoreParticipants(
(actualMembersCount - members.length).toString(),
),
),
leading: CircleAvatar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
child: const Icon(
Icons.refresh,
color: Colors.grey,
),
),
onTap: requestMoreMembersAction,
);
},
),
),
],
);
}

Widget _listMemberInfoMobileAndTablet(BuildContext context) {
if (!isMobileAndTablet) return const SizedBox.shrink();
return Column(
children: [
Container(
padding: const EdgeInsetsDirectional.all(16),
color: LinagoraSysColors.material().surface,
child: Align(
alignment: Alignment.centerLeft,
child: Text(
L10n.of(context)!.membersInfo(
actualMembersCount.toString(),
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.labelLarge?.copyWith(
color: LinagoraRefColors.material().neutral[40],
),
),
),
),
InkWell(
onTap: openDialogInvite,
child: Container(
padding: const EdgeInsetsDirectional.only(
start: 16.0,
top: 8.0,
bottom: 8.0,
),
margin: const EdgeInsetsDirectional.symmetric(
horizontal: 16.0,
vertical: 10.0,
),
child: Row(
children: [
Icon(
Icons.person_add,
size: 18,
color: LinagoraSysColors.material().primary,
),
const SizedBox(width: 8),
Text(
L10n.of(context)!.addMembers,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.labelLarge?.copyWith(
color: LinagoraSysColors.material().primary,
),
),
],
),
),
),
],
);
}
}
Loading

0 comments on commit 07fe67e

Please sign in to comment.