Skip to content

Commit 51c3dd5

Browse files
CubeRomanMagellanMagellan
andauthored
SK-609: Update UI for New chat Create group screen (#106)
* SK-567: flutter sdk development (#90) * create monorepo * add api * remove client old api * add tokens management * rename sama_chat_api to sama_sdk * SK-578: share to image (#91) * create monorepo * add api * remove client old api * add tokens management * rename sama_chat_api to sama_sdk * add image share to support * fix Popup with Send Image after share again --------- Co-authored-by: Magellan <magellan@connectycube.com> * add check for deleted user opponent (#93) Co-authored-by: Magellan <magellan@connectycube.com> * add MediaAttachmentBloc to menu (#95) Co-authored-by: Magellan <magellan@connectycube.com> * SK-589: implement ability to take a photo (#92) * create monorepo * add api * remove client old api * add tokens management * rename sama_chat_api to sama_sdk * add image share to support * add image_picker * add camera picker * update agpVersion --------- Co-authored-by: Magellan <magellan@connectycube.com> * SK-587: Hard back does not work (#94) * add pop invoke * minor fix didPop * add swipe ios impl --------- Co-authored-by: Magellan <magellan@connectycube.com> * fix app routing (#96) Co-authored-by: Magellan <magellan@connectycube.com> * add blocking (#97) Co-authored-by: Magellan <magellan@connectycube.com> * add auto complete (#98) Co-authored-by: Magellan <magellan@connectycube.com> * fix reply bubble (#99) Co-authored-by: Magellan <magellan@connectycube.com> * update login page * add expending to reset password * add fresh icons to chat list * update avatar view * update profile card * add card to profile * make fields more round * modify conversation_create_form * update create group button --------- Co-authored-by: Magellan <magellan@connectycube.com>
1 parent bb99f15 commit 51c3dd5

10 files changed

Lines changed: 287 additions & 145 deletions

File tree

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:go_router/go_router.dart';
3+
import '../../../navigation/constants.dart';
4+
import '../../../shared/ui/colors.dart';
5+
import '../../search/view/search_bar.dart';
6+
import '../../search/view/search_form.dart';
7+
8+
class ConversationCreateForm extends StatefulWidget {
9+
const ConversationCreateForm({super.key});
10+
11+
@override
12+
State<StatefulWidget> createState() {
13+
return ConversationCreateFormState();
14+
}
15+
}
16+
17+
class ConversationCreateFormState extends State<ConversationCreateForm> {
18+
@override
19+
void initState() {
20+
super.initState();
21+
}
22+
23+
@override
24+
Widget build(BuildContext context) {
25+
return Scaffold(
26+
appBar: const GlobalSearchBar(),
27+
body: Container(
28+
padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 4),
29+
child: Column(
30+
mainAxisSize: MainAxisSize.min,
31+
crossAxisAlignment: CrossAxisAlignment.start,
32+
children: [
33+
Row(children: <Widget>[
34+
Expanded(
35+
child: Padding(
36+
padding: const EdgeInsets.only(top: 20.0, bottom: 16.0),
37+
child: TextButton.icon(
38+
style: const ButtonStyle(
39+
backgroundColor: WidgetStatePropertyAll(slateBlue),
40+
),
41+
onPressed: () => context.push(groupCreateScreenPath),
42+
icon: const Icon(Icons.group_outlined,
43+
color: lightWhite, size: 25),
44+
label: const Text(
45+
'Create group',
46+
style: TextStyle(
47+
color: lightWhite,
48+
fontSize: 16,
49+
fontWeight: FontWeight.w500),
50+
),
51+
),
52+
),
53+
),
54+
]),
55+
const Expanded(
56+
child: Column(mainAxisSize: MainAxisSize.min, children: [
57+
Padding(
58+
padding: EdgeInsets.only(bottom: 8.0, top: 8.0),
59+
child: Align(
60+
alignment: Alignment.centerLeft,
61+
child: Text(
62+
'List of users:',
63+
style: TextStyle(
64+
fontWeight: FontWeight.bold, fontSize: 16),
65+
),
66+
),
67+
),
68+
SearchBody(searchType: SearchType.users)
69+
]))
70+
]),
71+
));
72+
}
73+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_bloc/flutter_bloc.dart';
3+
import 'package:go_router/go_router.dart';
4+
5+
import '../../../db/models/conversation_model.dart';
6+
import '../../../navigation/constants.dart';
7+
import '../../../repository/conversation/conversation_repository.dart';
8+
import '../../../repository/global_search/global_search_repository.dart';
9+
import '../../../shared/ui/view/loading_overlay.dart';
10+
import '../../conversation_create/bloc/conversation_create_bloc.dart';
11+
import '../../conversation_create/bloc/conversation_create_state.dart';
12+
import '../../search/bloc/global_search_bloc.dart';
13+
import '../../conversation_create/view/conversation_create_form.dart';
14+
15+
class ConversationCreatePage extends StatelessWidget {
16+
const ConversationCreatePage({super.key});
17+
18+
static MultiBlocProvider route() {
19+
return MultiBlocProvider(
20+
providers: [
21+
BlocProvider<GlobalSearchBloc>(
22+
create: (context) => GlobalSearchBloc(
23+
globalSearchRepository:
24+
RepositoryProvider.of<GlobalSearchRepository>(context),
25+
),
26+
),
27+
BlocProvider<ConversationCreateBloc>(
28+
create: (context) => ConversationCreateBloc(
29+
conversationRepository:
30+
RepositoryProvider.of<ConversationRepository>(context),
31+
),
32+
),
33+
],
34+
child: const ConversationCreatePage(),
35+
);
36+
}
37+
38+
@override
39+
Widget build(BuildContext context) {
40+
final LoadingOverlay loadingOverlay = LoadingOverlay();
41+
return BlocListener<ConversationCreateBloc, ConversationCreateState>(
42+
listener: (context, state) {
43+
if (state is ConversationCreatedLoading) {
44+
loadingOverlay.show(context);
45+
} else if (state is ConversationCreatedState) {
46+
loadingOverlay.hide();
47+
ConversationModel conversation = state.conversation;
48+
context.go('$conversationListScreenPath/$conversationScreenSubPath',
49+
extra: conversation);
50+
} else if (state is ConversationCreatedStateError) {
51+
loadingOverlay.hide();
52+
ScaffoldMessenger.of(context)
53+
..hideCurrentSnackBar()
54+
..showSnackBar(
55+
SnackBar(content: Text(state.error ?? '')),
56+
);
57+
}
58+
},
59+
child: const ConversationCreateForm());
60+
}
61+
}

sama_chat_client/lib/src/features/conversation_group_create/view/group_create_form.dart

Lines changed: 42 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_bloc/flutter_bloc.dart';
33
import 'package:formz/formz.dart';
4+
import 'package:sama_sdk/api/settings.dart';
45

56
import '../../../db/models/user_model.dart';
67
import '../../../features/conversation_create/bloc/conversation_create_event.dart';
78
import '../../../shared/ui/colors.dart';
89
import '../../../shared/ui/view/participants_forms.dart';
10+
import '../../../shared/ui/view/text_button_forms.dart';
911
import '../../../shared/utils/api_utils.dart';
1012
import '../../../shared/utils/screen_factor.dart';
1113
import '../../conversation_create/bloc/conversation_create_bloc.dart';
@@ -83,19 +85,23 @@ class GroupCreateFormState extends State<GroupCreateForm> {
8385
return previous.participants != current.participants;
8486
}, builder: (context, state) {
8587
return Visibility(
86-
visible: !keyboardIsOpenCtx(context),
87-
child: Visibility(
88-
visible: state.participants.isValid,
89-
child: FloatingActionButton(
90-
backgroundColor: slateBlue,
91-
tooltip: 'Next',
92-
onPressed: () {
93-
_showGroupDetails(context);
94-
},
95-
child: const Icon(Icons.arrow_forward, color: white, size: 28),
96-
),
97-
),
98-
);
88+
visible: !keyboardIsOpenCtx(context),
89+
child: Visibility(
90+
visible: state.participants.isValid,
91+
child: IntrinsicWidth(
92+
child: ButtonForm(
93+
onPressed: () {
94+
_showGroupDetails(context);
95+
},
96+
backgroundColor: WidgetStatePropertyAll(
97+
state.participants.isValid
98+
? slateBlue
99+
: whiteAluminum),
100+
foregroundColor: WidgetStatePropertyAll(
101+
state.participants.isValid ? white : gainsborough),
102+
hint: 'Next'),
103+
),
104+
));
99105
}));
100106
}
101107
}
@@ -119,16 +125,16 @@ void _showGroupDetails(BuildContext context) {
119125
value: BlocProvider.of<GroupBloc>(context),
120126
child: _GroupDetailsForm()),
121127
floatingActionButton: Visibility(
122-
visible: !keyboardIsOpenCtx(context),
123-
child: FloatingActionButton(
124-
backgroundColor: slateBlue,
125-
tooltip: 'Create chat',
126-
onPressed: () {
127-
context.read<GroupBloc>().add(GroupSubmitted());
128-
},
129-
child: const Icon(Icons.check, color: white, size: 28),
130-
),
131-
),
128+
visible: !keyboardIsOpenCtx(context),
129+
child: IntrinsicWidth(
130+
child: ButtonForm(
131+
onPressed: () {
132+
context.read<GroupBloc>().add(GroupSubmitted());
133+
},
134+
backgroundColor: const WidgetStatePropertyAll(slateBlue),
135+
foregroundColor: const WidgetStatePropertyAll(white),
136+
hint: 'Create'),
137+
)),
132138
)));
133139
}
134140

@@ -170,7 +176,7 @@ class _GroupDetailsForm extends StatelessWidget {
170176
padding: const EdgeInsets.only(top: 24.0),
171177
child: Align(
172178
alignment: Alignment.centerLeft,
173-
child: Text('Participants ${users.length}/$maxParticipantsCount',
179+
child: Text('Participants ${users.length + 1}/$maxParticipants',
174180
style: const TextStyle(
175181
fontWeight: FontWeight.bold, fontSize: 18)),
176182
),
@@ -189,14 +195,13 @@ class _GroupAvatar extends StatelessWidget {
189195
return GestureDetector(
190196
onTap: () => context.read<GroupBloc>().add(GroupAvatarPicked()),
191197
child: Container(
192-
decoration: BoxDecoration(
198+
decoration: const BoxDecoration(
193199
color: black,
194-
borderRadius: BorderRadius.circular(5.0),
200+
shape: BoxShape.circle,
195201
),
196-
padding: const EdgeInsets.all(4.0),
197202
height: 60.0,
198203
width: 60.0,
199-
child: Center(child: () {
204+
child: Center(child: ClipOval(child: () {
200205
if (state.avatar.value == null) {
201206
return const Icon(
202207
Icons.image_outlined,
@@ -212,7 +217,7 @@ class _GroupAvatar extends StatelessWidget {
212217
fit: BoxFit.cover,
213218
);
214219
}
215-
}())));
220+
}()))));
216221
});
217222
}
218223
}
@@ -223,43 +228,16 @@ class _GroupNameInput extends StatelessWidget {
223228
return BlocBuilder<GroupBloc, GroupState>(
224229
buildWhen: (previous, current) => previous.groupname != current.groupname,
225230
builder: (context, state) {
226-
return Container(
227-
height: 60.0,
228-
padding: const EdgeInsets.all(8),
229-
decoration: const BoxDecoration(
230-
borderRadius: BorderRadius.all(Radius.circular(12)),
231-
color: gainsborough,
232-
),
233-
child: TextField(
234-
key: const Key('groupCreateForm_groupnameInput_textField'),
235-
keyboardType: TextInputType.text,
231+
return TextFieldForm(
236232
onChanged: (groupname) =>
237233
context.read<GroupBloc>().add(GroupnameChanged(groupname)),
238-
decoration: InputDecoration(
239-
border: InputBorder.none,
240-
contentPadding: const EdgeInsets.only(bottom: 4),
241-
label: const Row(
242-
children: [
243-
Icon(
244-
Icons.group,
245-
size: 16,
246-
color: dullGray,
247-
),
248-
Text(
249-
'Groupname',
250-
style: TextStyle(color: dullGray, fontSize: 16),
251-
)
252-
],
253-
),
254-
errorText: state.groupname.displayError != null
255-
? state.groupname.displayError ==
256-
GroupnameValidationError.short
257-
? 'Group name is too short'
258-
: null
259-
: null,
260-
),
261-
),
262-
);
234+
iconData: Icons.group,
235+
hint: 'Groupname',
236+
error: state.groupname.displayError != null
237+
? state.groupname.displayError == GroupnameValidationError.short
238+
? 'Group name is too short'
239+
: null
240+
: null);
263241
},
264242
);
265243
}

sama_chat_client/lib/src/features/conversations_list/view/conversations_page.dart

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class ChatAppBar extends StatelessWidget implements PreferredSizeWidget {
102102
actions: <Widget>[
103103
ConnectionChecker(
104104
child: IconButton(
105-
onPressed: () => _openSearch(context),
105+
onPressed: () => context.push(conversationCreateScreenPath),
106106
icon: const Icon(
107107
Icons.edit_note_outlined,
108108
color: lightWhite,
@@ -114,11 +114,6 @@ class ChatAppBar extends StatelessWidget implements PreferredSizeWidget {
114114
);
115115
}
116116

117-
_openSearch(BuildContext context) {
118-
context.push(groupCreateScreenPath);
119-
// context.push(globalSearchPath);
120-
}
121-
122117
@override
123118
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
124119
}

sama_chat_client/lib/src/features/conversations_list/widgets/avatar_group_icon.dart

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,14 @@ class AvatarGroupIcon extends StatelessWidget {
1212
@override
1313
Widget build(BuildContext context) {
1414
return Container(
15-
decoration: BoxDecoration(
15+
decoration: const BoxDecoration(
1616
color: black,
17-
borderRadius: BorderRadius.circular(5.0),
17+
shape: BoxShape.circle,
1818
),
19-
padding: const EdgeInsets.all(4.0),
2019
height: size.height,
2120
width: size.width,
2221
child: Center(
23-
child: ClipRRect(
24-
borderRadius: BorderRadius.circular(5.0),
22+
child: ClipOval(
2523
child: avatar?.imageUrl != null
2624
? Image.network(
2725
avatar!.imageUrl!,

sama_chat_client/lib/src/features/conversations_list/widgets/avatar_letter_icon.dart

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ class AvatarLetterIcon extends StatelessWidget {
99
this.lastName,
1010
super.key,
1111
this.size = const Size(55, 60),
12-
this.borderRadius = 5.0,
13-
this.padding = const EdgeInsets.all(4.0),
12+
this.padding = EdgeInsets.zero,
1413
this.backgroundColor = black,
1514
this.textColor = dullGray,
1615
this.avatar,
@@ -21,7 +20,6 @@ class AvatarLetterIcon extends StatelessWidget {
2120
final String name;
2221
final String? lastName;
2322
final Size size;
24-
final double borderRadius;
2523
final EdgeInsetsGeometry padding;
2624
final Color backgroundColor;
2725
final Color textColor;
@@ -41,14 +39,14 @@ class AvatarLetterIcon extends StatelessWidget {
4139
return Container(
4240
decoration: BoxDecoration(
4341
color: backgroundColor,
44-
borderRadius: BorderRadius.circular(borderRadius),
42+
shape: BoxShape.circle,
43+
// border: Border.all(color: whiteAluminum, width: 2),
4544
),
46-
padding: padding,
45+
// padding: padding,
4746
height: size.height,
4847
width: size.width,
4948
child: Center(
50-
child: ClipRRect(
51-
borderRadius: BorderRadius.circular(borderRadius),
49+
child: ClipOval(
5250
child: avatar?.imageUrl != null
5351
? Image.network(
5452
avatar!.imageUrl!,

0 commit comments

Comments
 (0)