+ private Pair<Long, List<SendMessageResult>> quitGroupV1(final GroupInfoV1 groupInfoV1) throws IOException {
+ var group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.QUIT)
+ .withId(groupInfoV1.getGroupId().serialize())
+ .build();
+
+ var messageBuilder = SignalServiceDataMessage.newBuilder().asGroupMessage(group);
+ groupInfoV1.removeMember(account.getSelfRecipientId());
+ account.getGroupStore().updateGroup(groupInfoV1);
+ return sendMessage(messageBuilder, groupInfoV1.getMembersWithout(account.getSelfRecipientId()));
+ }
+
+ private Pair<Long, List<SendMessageResult>> quitGroupV2(
+ final GroupInfoV2 groupInfoV2, final Set<RecipientId> newAdmins
+ ) throws LastGroupAdminException, IOException {
+ final var currentAdmins = groupInfoV2.getAdminMembers();
+ newAdmins.removeAll(currentAdmins);
+ newAdmins.retainAll(groupInfoV2.getMembers());
+ if (currentAdmins.contains(getSelfRecipientId())
+ && currentAdmins.size() == 1
+ && groupInfoV2.getMembers().size() > 1
+ && newAdmins.size() == 0) {
+ // Last admin can't leave the group, unless she's also the last member
+ throw new LastGroupAdminException(groupInfoV2.getGroupId(), groupInfoV2.getTitle());
+ }
+ final var groupGroupChangePair = groupV2Helper.leaveGroup(groupInfoV2, newAdmins);
+ groupInfoV2.setGroup(groupGroupChangePair.first(), this::resolveRecipient);
+ var messageBuilder = getGroupUpdateMessageBuilder(groupInfoV2, groupGroupChangePair.second().toByteArray());
+ account.getGroupStore().updateGroup(groupInfoV2);
+ return sendMessage(messageBuilder, groupInfoV2.getMembersWithout(account.getSelfRecipientId()));
+ }
+
+ public void deleteGroup(GroupId groupId) throws IOException {
+ account.getGroupStore().deleteGroup(groupId);
+ avatarStore.deleteGroupAvatar(groupId);