mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-25 22:39:22 +00:00
Can create group conversations
This commit is contained in:
parent
07b42df06a
commit
054b2a1d32
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:comunic/helpers/groups_helper.dart';
|
||||||
import 'package:comunic/helpers/serialization/conversation_message_serialization_helper.dart';
|
import 'package:comunic/helpers/serialization/conversation_message_serialization_helper.dart';
|
||||||
import 'package:comunic/helpers/serialization/conversations_serialization_helper.dart';
|
import 'package:comunic/helpers/serialization/conversations_serialization_helper.dart';
|
||||||
import 'package:comunic/helpers/users_helper.dart';
|
import 'package:comunic/helpers/users_helper.dart';
|
||||||
@ -238,6 +239,8 @@ class ConversationsHelper {
|
|||||||
color: map["color"] == null ? null : HexColor(map["color"]),
|
color: map["color"] == null ? null : HexColor(map["color"]),
|
||||||
logoURL: map["logo"],
|
logoURL: map["logo"],
|
||||||
groupID: map["group_id"],
|
groupID: map["group_id"],
|
||||||
|
groupMinMembershipLevel:
|
||||||
|
APIGroupsMembershipLevelsMap[map["group_min_membership_level"]],
|
||||||
members: map["members"]
|
members: map["members"]
|
||||||
.cast<Map<String, dynamic>>()
|
.cast<Map<String, dynamic>>()
|
||||||
.map(apiToConversationMember)
|
.map(apiToConversationMember)
|
||||||
|
@ -6,6 +6,7 @@ import 'package:comunic/models/advanced_group_info.dart';
|
|||||||
import 'package:comunic/models/api_request.dart';
|
import 'package:comunic/models/api_request.dart';
|
||||||
import 'package:comunic/models/group.dart';
|
import 'package:comunic/models/group.dart';
|
||||||
import 'package:comunic/models/group_membership.dart';
|
import 'package:comunic/models/group_membership.dart';
|
||||||
|
import 'package:comunic/models/new_group_conversation.dart';
|
||||||
import 'package:comunic/utils/api_utils.dart';
|
import 'package:comunic/utils/api_utils.dart';
|
||||||
import 'package:comunic/utils/map_utils.dart';
|
import 'package:comunic/utils/map_utils.dart';
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ import 'package:comunic/utils/map_utils.dart';
|
|||||||
///
|
///
|
||||||
/// @author Pierre HUBERT
|
/// @author Pierre HUBERT
|
||||||
|
|
||||||
const _APIGroupsMembershipLevelsMap = {
|
const APIGroupsMembershipLevelsMap = {
|
||||||
"administrator": GroupMembershipLevel.ADMINISTRATOR,
|
"administrator": GroupMembershipLevel.ADMINISTRATOR,
|
||||||
"moderator": GroupMembershipLevel.MODERATOR,
|
"moderator": GroupMembershipLevel.MODERATOR,
|
||||||
"member": GroupMembershipLevel.MEMBER,
|
"member": GroupMembershipLevel.MEMBER,
|
||||||
@ -326,7 +327,22 @@ class GroupsHelper {
|
|||||||
await APIRequest.withLogin("groups/update_membership_level")
|
await APIRequest.withLogin("groups/update_membership_level")
|
||||||
.addInt("groupID", groupID)
|
.addInt("groupID", groupID)
|
||||||
.addInt("userID", userID)
|
.addInt("userID", userID)
|
||||||
.addString("level", invertMap(_APIGroupsMembershipLevelsMap)[level])
|
.addString("level", invertMap(APIGroupsMembershipLevelsMap)[level])
|
||||||
|
.execWithThrow();
|
||||||
|
|
||||||
|
/// Create a new group conversation
|
||||||
|
///
|
||||||
|
/// Throws in case of failure
|
||||||
|
static Future<void> createGroupConversation(
|
||||||
|
NewGroupConversation conv) async =>
|
||||||
|
await APIRequest.withLogin("groups/create_conversation")
|
||||||
|
.addInt("group_id", conv.groupID)
|
||||||
|
.addString(
|
||||||
|
"min_membership_level",
|
||||||
|
APIGroupsMembershipLevelsMap.entries
|
||||||
|
.firstWhere((e) => e.value == conv.minMembershipLevel)
|
||||||
|
.key)
|
||||||
|
.addString("name", conv.name)
|
||||||
.execWithThrow();
|
.execWithThrow();
|
||||||
|
|
||||||
/// Turn an API entry into a group object
|
/// Turn an API entry into a group object
|
||||||
@ -336,7 +352,7 @@ class GroupsHelper {
|
|||||||
name: map["name"],
|
name: map["name"],
|
||||||
iconURL: map["icon_url"],
|
iconURL: map["icon_url"],
|
||||||
numberMembers: map["number_members"],
|
numberMembers: map["number_members"],
|
||||||
membershipLevel: _APIGroupsMembershipLevelsMap[map["membership"]],
|
membershipLevel: APIGroupsMembershipLevelsMap[map["membership"]],
|
||||||
visibilityLevel: _APIGroupsVisibilityLevelsMap[map["visibility"]],
|
visibilityLevel: _APIGroupsVisibilityLevelsMap[map["visibility"]],
|
||||||
registrationLevel:
|
registrationLevel:
|
||||||
_APIGroupsRegistrationLevelsMap[map["registration_level"]],
|
_APIGroupsRegistrationLevelsMap[map["registration_level"]],
|
||||||
@ -352,7 +368,7 @@ class GroupsHelper {
|
|||||||
name: map["name"],
|
name: map["name"],
|
||||||
iconURL: map["icon_url"],
|
iconURL: map["icon_url"],
|
||||||
numberMembers: map["number_members"],
|
numberMembers: map["number_members"],
|
||||||
membershipLevel: _APIGroupsMembershipLevelsMap[map["membership"]],
|
membershipLevel: APIGroupsMembershipLevelsMap[map["membership"]],
|
||||||
visibilityLevel: _APIGroupsVisibilityLevelsMap[map["visibility"]],
|
visibilityLevel: _APIGroupsVisibilityLevelsMap[map["visibility"]],
|
||||||
registrationLevel:
|
registrationLevel:
|
||||||
_APIGroupsRegistrationLevelsMap[map["registration_level"]],
|
_APIGroupsRegistrationLevelsMap[map["registration_level"]],
|
||||||
@ -373,6 +389,6 @@ class GroupsHelper {
|
|||||||
userID: row["user_id"],
|
userID: row["user_id"],
|
||||||
groupID: row["group_id"],
|
groupID: row["group_id"],
|
||||||
timeCreate: row["time_create"],
|
timeCreate: row["time_create"],
|
||||||
level: _APIGroupsMembershipLevelsMap[row["level"]],
|
level: APIGroupsMembershipLevelsMap[row["level"]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,8 @@ class ServerConfigurationHelper {
|
|||||||
minLikesLifetime: dataConservationPolicy["min_likes_lifetime"],
|
minLikesLifetime: dataConservationPolicy["min_likes_lifetime"],
|
||||||
),
|
),
|
||||||
conversationsPolicy: ConversationsPolicy(
|
conversationsPolicy: ConversationsPolicy(
|
||||||
|
maxConversationNameLen:
|
||||||
|
conversationsPolicy["max_conversation_name_len"],
|
||||||
minMessageLen: conversationsPolicy["min_message_len"],
|
minMessageLen: conversationsPolicy["min_message_len"],
|
||||||
maxMessageLen: conversationsPolicy["max_message_len"],
|
maxMessageLen: conversationsPolicy["max_message_len"],
|
||||||
allowedFilesType:
|
allowedFilesType:
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:comunic/enums/likes_type.dart';
|
import 'package:comunic/enums/likes_type.dart';
|
||||||
|
import 'package:comunic/models/conversation.dart';
|
||||||
import 'package:comunic/models/like_element.dart';
|
import 'package:comunic/models/like_element.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ class AdvancedGroupInfo extends Group implements LikeElement {
|
|||||||
String url;
|
String url;
|
||||||
int likes;
|
int likes;
|
||||||
bool userLike;
|
bool userLike;
|
||||||
|
List<Conversation> conversations;
|
||||||
|
|
||||||
AdvancedGroupInfo({
|
AdvancedGroupInfo({
|
||||||
@required int id,
|
@required int id,
|
||||||
|
@ -4,6 +4,8 @@ import 'package:comunic/utils/account_utils.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
import 'group.dart';
|
||||||
|
|
||||||
/// Conversation model
|
/// Conversation model
|
||||||
///
|
///
|
||||||
/// @author Pierre HUBERT
|
/// @author Pierre HUBERT
|
||||||
@ -17,6 +19,7 @@ class Conversation extends SerializableElement<Conversation> {
|
|||||||
final Color color;
|
final Color color;
|
||||||
final String logoURL;
|
final String logoURL;
|
||||||
final int groupID;
|
final int groupID;
|
||||||
|
final GroupMembershipLevel groupMinMembershipLevel;
|
||||||
final List<ConversationMember> members;
|
final List<ConversationMember> members;
|
||||||
final bool canEveryoneAddMembers;
|
final bool canEveryoneAddMembers;
|
||||||
final CallCapabilities callCapabilities;
|
final CallCapabilities callCapabilities;
|
||||||
@ -29,6 +32,7 @@ class Conversation extends SerializableElement<Conversation> {
|
|||||||
@required this.color,
|
@required this.color,
|
||||||
@required this.logoURL,
|
@required this.logoURL,
|
||||||
@required this.groupID,
|
@required this.groupID,
|
||||||
|
@required this.groupMinMembershipLevel,
|
||||||
@required this.members,
|
@required this.members,
|
||||||
@required this.canEveryoneAddMembers,
|
@required this.canEveryoneAddMembers,
|
||||||
this.callCapabilities = CallCapabilities.NONE,
|
this.callCapabilities = CallCapabilities.NONE,
|
||||||
@ -37,6 +41,7 @@ class Conversation extends SerializableElement<Conversation> {
|
|||||||
assert(lastActivity != null),
|
assert(lastActivity != null),
|
||||||
assert(members != null),
|
assert(members != null),
|
||||||
assert(canEveryoneAddMembers != null),
|
assert(canEveryoneAddMembers != null),
|
||||||
|
assert((groupID == null) == (groupMinMembershipLevel == null)),
|
||||||
assert(callCapabilities != null),
|
assert(callCapabilities != null),
|
||||||
assert(isHavingCall != null);
|
assert(isHavingCall != null);
|
||||||
|
|
||||||
@ -78,6 +83,9 @@ class Conversation extends SerializableElement<Conversation> {
|
|||||||
color = map["color"] == null ? null : Color(map["color"]),
|
color = map["color"] == null ? null : Color(map["color"]),
|
||||||
logoURL = map["logoURL"],
|
logoURL = map["logoURL"],
|
||||||
groupID = map["groupID"],
|
groupID = map["groupID"],
|
||||||
|
groupMinMembershipLevel = GroupMembershipLevel.values.firstWhere(
|
||||||
|
(element) => element.toString() == map["groupMinMembershipLevel"],
|
||||||
|
orElse: () => null),
|
||||||
lastActivity = map["lastActivity"],
|
lastActivity = map["lastActivity"],
|
||||||
members = map["members"]
|
members = map["members"]
|
||||||
.map((el) => ConversationMember.fromJSON(el))
|
.map((el) => ConversationMember.fromJSON(el))
|
||||||
@ -96,6 +104,7 @@ class Conversation extends SerializableElement<Conversation> {
|
|||||||
"color": color?.value,
|
"color": color?.value,
|
||||||
"logoURL": logoURL,
|
"logoURL": logoURL,
|
||||||
"groupID": groupID,
|
"groupID": groupID,
|
||||||
|
"groupMinMembershipLevel": groupMinMembershipLevel?.toString(),
|
||||||
"lastActivity": lastActivity,
|
"lastActivity": lastActivity,
|
||||||
"members": members.map((e) => e.toJson()).toList(),
|
"members": members.map((e) => e.toJson()).toList(),
|
||||||
"canEveryoneAddMembers": canEveryoneAddMembers,
|
"canEveryoneAddMembers": canEveryoneAddMembers,
|
||||||
|
21
lib/models/new_group_conversation.dart
Normal file
21
lib/models/new_group_conversation.dart
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import 'package:comunic/models/group.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
/// This class contains information about a conversation linked to a group
|
||||||
|
/// to create
|
||||||
|
///
|
||||||
|
/// @author Pierre Hubert
|
||||||
|
|
||||||
|
class NewGroupConversation {
|
||||||
|
final int groupID;
|
||||||
|
final String name;
|
||||||
|
final GroupMembershipLevel minMembershipLevel;
|
||||||
|
|
||||||
|
const NewGroupConversation({
|
||||||
|
@required this.groupID,
|
||||||
|
@required this.name,
|
||||||
|
@required this.minMembershipLevel,
|
||||||
|
}) : assert(groupID != null),
|
||||||
|
assert(name != null),
|
||||||
|
assert(minMembershipLevel != null);
|
||||||
|
}
|
@ -58,6 +58,7 @@ class ServerDataConservationPolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ConversationsPolicy {
|
class ConversationsPolicy {
|
||||||
|
final int maxConversationNameLen;
|
||||||
final int minMessageLen;
|
final int minMessageLen;
|
||||||
final int maxMessageLen;
|
final int maxMessageLen;
|
||||||
final List<String> allowedFilesType;
|
final List<String> allowedFilesType;
|
||||||
@ -72,6 +73,7 @@ class ConversationsPolicy {
|
|||||||
final int maxLogoHeight;
|
final int maxLogoHeight;
|
||||||
|
|
||||||
const ConversationsPolicy({
|
const ConversationsPolicy({
|
||||||
|
@required this.maxConversationNameLen,
|
||||||
@required this.minMessageLen,
|
@required this.minMessageLen,
|
||||||
@required this.maxMessageLen,
|
@required this.maxMessageLen,
|
||||||
@required this.allowedFilesType,
|
@required this.allowedFilesType,
|
||||||
@ -84,7 +86,8 @@ class ConversationsPolicy {
|
|||||||
@required this.maxThumbnailHeight,
|
@required this.maxThumbnailHeight,
|
||||||
@required this.maxLogoWidth,
|
@required this.maxLogoWidth,
|
||||||
@required this.maxLogoHeight,
|
@required this.maxLogoHeight,
|
||||||
}) : assert(minMessageLen != null),
|
}) : assert(maxConversationNameLen != null),
|
||||||
|
assert(minMessageLen != null),
|
||||||
assert(maxMessageLen != null),
|
assert(maxMessageLen != null),
|
||||||
assert(allowedFilesType != null),
|
assert(allowedFilesType != null),
|
||||||
assert(filesMaxSize != null),
|
assert(filesMaxSize != null),
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:comunic/helpers/groups_helper.dart';
|
import 'package:comunic/helpers/groups_helper.dart';
|
||||||
|
import 'package:comunic/helpers/server_config_helper.dart';
|
||||||
import 'package:comunic/models/advanced_group_info.dart';
|
import 'package:comunic/models/advanced_group_info.dart';
|
||||||
import 'package:comunic/models/group.dart';
|
import 'package:comunic/models/group.dart';
|
||||||
|
import 'package:comunic/models/new_group_conversation.dart';
|
||||||
import 'package:comunic/ui/dialogs/input_user_password_dialog.dart';
|
import 'package:comunic/ui/dialogs/input_user_password_dialog.dart';
|
||||||
import 'package:comunic/ui/dialogs/multi_choices_dialog.dart';
|
import 'package:comunic/ui/dialogs/multi_choices_dialog.dart';
|
||||||
import 'package:comunic/ui/dialogs/virtual_directory_dialog.dart';
|
import 'package:comunic/ui/dialogs/virtual_directory_dialog.dart';
|
||||||
@ -17,6 +19,7 @@ import 'package:comunic/ui/widgets/settings/text_settings_edit_tile.dart';
|
|||||||
import 'package:comunic/utils/files_utils.dart';
|
import 'package:comunic/utils/files_utils.dart';
|
||||||
import 'package:comunic/utils/input_utils.dart';
|
import 'package:comunic/utils/input_utils.dart';
|
||||||
import 'package:comunic/utils/intl_utils.dart';
|
import 'package:comunic/utils/intl_utils.dart';
|
||||||
|
import 'package:comunic/utils/log_utils.dart';
|
||||||
import 'package:comunic/utils/ui_utils.dart';
|
import 'package:comunic/utils/ui_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:identicon/identicon.dart';
|
import 'package:identicon/identicon.dart';
|
||||||
@ -85,6 +88,7 @@ class _GroupSettingsScreenState extends SafeState<GroupSettingsScreen> {
|
|||||||
HeadSpacerSection(),
|
HeadSpacerSection(),
|
||||||
_buildGeneralSection(),
|
_buildGeneralSection(),
|
||||||
_buildAccessRestrictions(),
|
_buildAccessRestrictions(),
|
||||||
|
_buildConversationsArea(),
|
||||||
_buildGroupLogoArea(),
|
_buildGroupLogoArea(),
|
||||||
_buildDangerZone(),
|
_buildDangerZone(),
|
||||||
],
|
],
|
||||||
@ -256,6 +260,75 @@ class _GroupSettingsScreenState extends SafeState<GroupSettingsScreen> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
List<MultiChoiceEntry<GroupMembershipLevel>>
|
||||||
|
get _conversationMinMembershipLevel => [
|
||||||
|
MultiChoiceEntry(
|
||||||
|
id: GroupMembershipLevel.ADMINISTRATOR,
|
||||||
|
title: tr("Administrators only"),
|
||||||
|
subtitle: tr(
|
||||||
|
"Only the administrators of the group can access the conversation"),
|
||||||
|
),
|
||||||
|
MultiChoiceEntry(
|
||||||
|
id: GroupMembershipLevel.MODERATOR,
|
||||||
|
title: tr("Moderators and administrators"),
|
||||||
|
subtitle: tr(
|
||||||
|
"Only moderators and administrators of the group can access the conversation"),
|
||||||
|
),
|
||||||
|
MultiChoiceEntry(
|
||||||
|
id: GroupMembershipLevel.MEMBER,
|
||||||
|
title: tr("All members"),
|
||||||
|
subtitle: tr(
|
||||||
|
"All the members of the group can access the conversation"),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
SettingsSection _buildConversationsArea() => SettingsSection(
|
||||||
|
title: tr("Group conversations"),
|
||||||
|
tiles: [
|
||||||
|
SettingsTile(
|
||||||
|
title: tr("Create a new conversation"),
|
||||||
|
onPressed: _createNewGroupConversation,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
void _createNewGroupConversation(BuildContext context) async {
|
||||||
|
try {
|
||||||
|
final name = await askUserString(
|
||||||
|
context: context,
|
||||||
|
title: tr("New conversation name"),
|
||||||
|
message: tr("Please give a name to the new conversation"),
|
||||||
|
defaultValue: "",
|
||||||
|
hint: tr("Name"),
|
||||||
|
minLength: 1,
|
||||||
|
maxLength: ServerConfigurationHelper
|
||||||
|
.config.conversationsPolicy.maxConversationNameLen,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (name == null) return;
|
||||||
|
|
||||||
|
final visibility = await showMultiChoicesDialog(
|
||||||
|
context: context,
|
||||||
|
choices: _conversationMinMembershipLevel,
|
||||||
|
defaultChoice: GroupMembershipLevel.MEMBER,
|
||||||
|
title: tr("Conversation visibility"),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (visibility == null) return;
|
||||||
|
|
||||||
|
await GroupsHelper.createGroupConversation(NewGroupConversation(
|
||||||
|
groupID: _groupSettings.id,
|
||||||
|
name: name,
|
||||||
|
minMembershipLevel: visibility,
|
||||||
|
));
|
||||||
|
|
||||||
|
_key.currentState.refresh();
|
||||||
|
} catch (e, s) {
|
||||||
|
logError(e, s);
|
||||||
|
snack(context, tr("Failed to create a conversation!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildGroupLogoArea() {
|
Widget _buildGroupLogoArea() {
|
||||||
return SettingsSection(
|
return SettingsSection(
|
||||||
title: tr("Group logo"),
|
title: tr("Group logo"),
|
||||||
|
Loading…
Reference in New Issue
Block a user