Skip to content

Commit

Permalink
feat: preview loaded picture on group creation
Browse files Browse the repository at this point in the history
  • Loading branch information
Julian KOUNE committed Jun 13, 2023
1 parent 9b48f50 commit 1fe6cd9
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 79 deletions.
1 change: 0 additions & 1 deletion lib/pages/new_group/new_group.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ class NewGroupController extends State<NewGroup> with ComparablePresentationCont

String groupName = "";
bool isGroupPrivate = false;
MatrixFile? avatar;

@override
void initState() {
Expand Down
120 changes: 98 additions & 22 deletions lib/pages/new_group/new_group_chat_info.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:file_picker_cross/file_picker_cross.dart';
import 'package:fluffychat/pages/settings/settings.dart';
import 'package:fluffychat/presentation/model/presentation_contact.dart';
import 'package:fluffychat/pages/new_group/new_group.dart';
import 'package:fluffychat/pages/new_group/new_group_info_controller.dart';
import 'package:fluffychat/pages/new_group/widget/expansion_participants_list.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/widgets/setting_tile.dart';
import 'package:fluffychat/widgets/twake_components/twake_fab.dart';
import 'package:fluffychat/widgets/twake_components/twake_icon_button.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:linagora_design_flutter/colors/linagora_ref_colors.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:matrix/matrix.dart';


class NewGroupChatInfo extends StatelessWidget {
class NewGroupChatInfo extends StatefulWidget {

final Set<PresentationContact> contactsList;

Expand All @@ -22,6 +28,13 @@ class NewGroupChatInfo extends StatelessWidget {
required this.newGroupController,
});

@override
State<NewGroupChatInfo> createState() => _NewGroupChatInfoState();
}

class _NewGroupChatInfoState extends State<NewGroupChatInfo> {
MatrixFile? localAvatar;

@override
Widget build(BuildContext context) {
return Scaffold(
Expand All @@ -46,13 +59,15 @@ class NewGroupChatInfo extends StatelessWidget {
const SizedBox(height: 16,),
_buildSettings(context),
Expanded(
child: ExpansionParticipantsList(contactsList: contactsList,),
child: ExpansionParticipantsList(
contactsList: widget.contactsList,
),
),
],
),
),
floatingActionButton: ValueListenableBuilder<bool>(
valueListenable: newGroupController.haveGroupNameNotifier,
valueListenable: widget.newGroupController.haveGroupNameNotifier,
builder: (context, value, child) {
if (!value) {
return const SizedBox.shrink();
Expand All @@ -61,7 +76,7 @@ class NewGroupChatInfo extends StatelessWidget {
},
child: TwakeFloatingActionButton(
icon: Icons.done,
onTap: () => newGroupController.moveToGroupChatScreen(),
onTap: () => widget.newGroupController.moveToGroupChatScreen(localAvatar),
),
),
);
Expand Down Expand Up @@ -115,27 +130,39 @@ class NewGroupChatInfo extends StatelessWidget {

Widget _buildChangeProfileWidget(BuildContext context) {
return GestureDetector(
onTap: () => newGroupController.saveAvatarAction(context),
child: Container(
width: 56,
height: 56,
decoration: BoxDecoration(
color: LinagoraRefColors.material().neutral[80],
shape: BoxShape.circle,
),
alignment: Alignment.center,
child: Icon(Icons.camera_alt_outlined,
color: Theme.of(context).colorScheme.surface,
),
),
);
onTap: () => saveAvatarAction(context),
child: localAvatar == null
? Container(
width: 56,
height: 56,
decoration: BoxDecoration(
color: LinagoraRefColors.material().neutral[80],
shape: BoxShape.circle,
),
alignment: Alignment.center,
child: Icon(
Icons.camera_alt_outlined,
color: Theme.of(context).colorScheme.surface,
),
)
: Container(
width: 56,
height: 56,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: MemoryImage(localAvatar!.bytes),
fit: BoxFit.cover,
),
),
));
}

Widget _buildGroupNameTextField(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: TextField(
controller: newGroupController.groupNameTextEditingController,
controller: widget.newGroupController.groupNameTextEditingController,
decoration: InputDecoration(
border: OutlineInputBorder(
borderSide: BorderSide(color: Theme.of(context).colorScheme.shadow),
Expand Down Expand Up @@ -168,11 +195,11 @@ class NewGroupChatInfo extends StatelessWidget {
settingTitle: L10n.of(context)!.makeThisGroupPrivate,
settingDescription: L10n.of(context)!.groupPrivateDescription,
onSwitchButtonChanged: (valueChanged)
=> newGroupController.onGroupPrivacyChanged(valueChanged),
defaultSwitchValue: newGroupController.isGroupPrivate,
=> widget.newGroupController.onGroupPrivacyChanged(valueChanged),
defaultSwitchValue: widget.newGroupController.isGroupPrivate,
),
ValueListenableBuilder<bool>(
valueListenable: newGroupController.isEnableEEEncryptionNotifier,
valueListenable: widget.newGroupController.isEnableEEEncryptionNotifier,
builder: (context, value, child) {
return SettingTile(
key: UniqueKey(),
Expand All @@ -188,4 +215,53 @@ class NewGroupChatInfo extends StatelessWidget {
),
);
}

void saveAvatarAction(BuildContext context) async {
final actions = [
if (PlatformInfos.isMobile)
SheetAction(
key: AvatarAction.camera,
label: L10n.of(context)!.openCamera,
isDefaultAction: true,
icon: Icons.camera_alt_outlined,
),
SheetAction(
key: AvatarAction.file,
label: L10n.of(context)!.openGallery,
icon: Icons.photo_outlined,
),
];
final action = actions.length == 1
? actions.single.key
: await showModalActionSheet<AvatarAction>(
context: context,
title: L10n.of(context)!.changeGroupAvatar,
actions: actions,
);
if (action == null) return;

MatrixFile file;
if (PlatformInfos.isMobile) {
final result = await ImagePicker().pickImage(
source: action == AvatarAction.camera ? ImageSource.camera : ImageSource.gallery,
imageQuality: 50,
);
if (result == null) return;
file = MatrixFile(
bytes: await result.readAsBytes(),
name: result.path,
);
} else {
final result = await FilePickerCross.importFromStorage(type: FileTypeCross.image);
if (result.fileName == null) return;
file = MatrixFile(
bytes: result.toUint8List(),
name: result.fileName!,
);
}

setState(() {
localAvatar = file;
});
}
}
58 changes: 2 additions & 56 deletions lib/pages/new_group/new_group_info_controller.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:file_picker_cross/file_picker_cross.dart';
import 'package:fluffychat/pages/settings/settings.dart';
import 'package:fluffychat/presentation/model/presentation_contact.dart';
import 'package:fluffychat/pages/new_group/new_group.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/utils/string_extension.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:matrix/matrix.dart';
import 'package:vrouter/vrouter.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';

extension NewGroupInfoController on NewGroupController {

Expand All @@ -21,7 +14,7 @@ extension NewGroupInfoController on NewGroupController {
});
}

void moveToGroupChatScreen() async {
void moveToGroupChatScreen(MatrixFile? avatar) async {
final client = Matrix.of(context).client;
final roomId = await client.createGroupChat(
groupName: groupName,
Expand All @@ -35,7 +28,7 @@ extension NewGroupInfoController on NewGroupController {
);

if (roomId.isNotEmpty && avatar != null) {
await client.getRoomById(roomId)!.setAvatar(avatar!);
await client.getRoomById(roomId)!.setAvatar(avatar);
}

VRouter.of(context).toSegments(['rooms', roomId]);
Expand All @@ -53,51 +46,4 @@ extension NewGroupInfoController on NewGroupController {
.where((contact) => contact.matrixId != null && !contact.matrixId!.isCurrentMatrixId(context))
.toSet();
}

void saveAvatarAction(BuildContext context) async {
final actions = [
if (PlatformInfos.isMobile)
SheetAction(
key: AvatarAction.camera,
label: L10n.of(context)!.openCamera,
isDefaultAction: true,
icon: Icons.camera_alt_outlined,
),
SheetAction(
key: AvatarAction.file,
label: L10n.of(context)!.openGallery,
icon: Icons.photo_outlined,
),
];
final action = actions.length == 1
? actions.single.key
: await showModalActionSheet<AvatarAction>(
context: context,
title: L10n.of(context)!.changeGroupAvatar,
actions: actions,
);
if (action == null) return;

MatrixFile file;
if (PlatformInfos.isMobile) {
final result = await ImagePicker().pickImage(
source: action == AvatarAction.camera ? ImageSource.camera : ImageSource.gallery,
imageQuality: 50,
);
if (result == null) return;
file = MatrixFile(
bytes: await result.readAsBytes(),
name: result.path,
);
} else {
final result = await FilePickerCross.importFromStorage(type: FileTypeCross.image);
if (result.fileName == null) return;
file = MatrixFile(
bytes: result.toUint8List(),
name: result.fileName!,
);
}

avatar = file;
}
}

0 comments on commit 1fe6cd9

Please sign in to comment.