[Merge] lp:history-service/staging into lp:history-service

Gustavo Pichorim Boiko gustavo.boiko at canonical.com
Thu Nov 24 01:57:36 UTC 2016


Debug prints removed, question answered and loops changed on a separate MR.

Diff comments:

> 
> === modified file 'Ubuntu/History/historymodel.cpp'
> --- Ubuntu/History/historymodel.cpp	2015-10-08 21:52:59 +0000
> +++ Ubuntu/History/historymodel.cpp	2016-10-20 14:04:14 +0000
> @@ -89,16 +92,98 @@
>      case TypeRole:
>          result = properties[History::FieldType];
>          break;
> -    case ParticipantsRole:
> +    case ParticipantsRole: {
> +        // FIXME: reimplement in a cleaner way
> +        History::Participants participants = History::Participants::fromVariantList(properties[History::FieldParticipants].toList());
>          if (mMatchContacts) {
> -            result = History::ContactMatcher::instance()->contactInfo(properties[History::FieldAccountId].toString(),
> -                                                                      History::Participants::fromVariantList(properties[History::FieldParticipants].toList()).identifiers());
> +            QVariantList finalParticipantsList;
> +            QVariantList participantsInfo = History::ContactMatcher::instance()->contactInfo(properties[History::FieldAccountId].toString(),
> +                                                                      participants.identifiers());
> +            int count = 0;
> +            Q_FOREACH(const QVariant &participantInfo, participantsInfo) {
> +                QVariantMap newMap = participantInfo.toMap();
> +                if (participants.at(count).state() != History::ParticipantStateRegular) {
> +                   count++;
> +                   continue;
> +                }
> +                newMap[History::FieldParticipantState] = participants.at(count).state();
> +                newMap[History::FieldParticipantRoles] = participants.at(count++).roles();
> +                finalParticipantsList << newMap;
> +            }

All those Q_FOREACH() comments were addressed here:
https://code.launchpad.net/~phablet-team/history-service/simplify_participant_filtering/+merge/311674

> +            result = finalParticipantsList;
>          } else {
>              //FIXME: handle contact changes
>              result = properties[History::FieldParticipants];
>          }
>          break;
>      }
> +    case ParticipantsRemotePendingRole: {
> +        // FIXME: reimplement in a cleaner way
> +        QStringList identifiers;
> +        History::Participants participants;
> +        // filter remote pending participants
> +        Q_FOREACH(const History::Participant &participant, History::Participants::fromVariantList(properties[History::FieldParticipants].toList())) {
> +            if (participant.state() == History::ParticipantStateRemotePending) {
> +                participants << participant;
> +            }
> +        }
> +
> +        if (mMatchContacts) {
> +            QVariantList finalParticipantsList;
> +            QVariantList participantsInfo = History::ContactMatcher::instance()->contactInfo(properties[History::FieldAccountId].toString(),
> +                                                                      participants.identifiers());
> +            int count = 0;
> +            Q_FOREACH(const QVariant &participantInfo, participantsInfo) {
> +                QVariantMap newMap = participantInfo.toMap();
> +                newMap[History::FieldParticipantState] = participants.at(count).state();
> +                newMap[History::FieldParticipantRoles] = participants.at(count++).roles();
> +                finalParticipantsList << newMap;
> +            }
> +            result = finalParticipantsList;
> +        } else {
> +            //FIXME: handle contact changes
> +            result = participants.identifiers();
> +        }
> +
> +        break;
> +    }
> +    case ParticipantsLocalPendingRole: {
> +        // FIXME: reimplement in a cleaner way
> +        QStringList identifiers;
> +        History::Participants participants;
> +        Q_FOREACH(const History::Participant &participant, History::Participants::fromVariantList(properties[History::FieldParticipants].toList())) {
> +            if (participant.state() == History::ParticipantStateLocalPending) {
> +                participants << participant;
> +            }
> +        }
> +
> +        if (mMatchContacts) {
> +            QVariantList finalParticipantsList;
> +            QVariantList participantsInfo = History::ContactMatcher::instance()->contactInfo(properties[History::FieldAccountId].toString(),
> +                                                                      identifiers);
> +            int count = 0;
> +            Q_FOREACH(const QVariant &participantInfo, participantsInfo) {
> +                QVariantMap newMap = participantInfo.toMap();
> +                newMap[History::FieldParticipantState] = participants.at(count).state();
> +                newMap[History::FieldParticipantRoles] = participants.at(count++).roles();
> +                finalParticipantsList << newMap;
> +            }
> +            result = finalParticipantsList;
> +        } else {
> +            //FIXME: handle contact changes
> +            result = identifiers;
> +        }
> +
> +        break;
> +    }
> +    case ParticipantIdsRole:
> +        result = History::Participants::fromVariantList(properties[History::FieldParticipants].toList()).identifiers();
> +        break;
> +    case TimestampRole:
> +        result = QDateTime::fromString(properties[History::FieldTimestamp].toString(), Qt::ISODate);
> +        break;
> +    }
> +
>      return result;
>  }
>  
> 
> === modified file 'daemon/historydaemon.cpp'
> --- daemon/historydaemon.cpp	2015-11-20 12:53:49 +0000
> +++ daemon/historydaemon.cpp	2016-10-20 14:04:14 +0000
> @@ -414,8 +613,270 @@
>      event[History::FieldMissed] = missed;
>      event[History::FieldDuration] = duration;
>      // FIXME: check what to do when there are more than just one remote participant
> -    event[History::FieldRemoteParticipant] = participants[0];
> -    writeEvents(QList<QVariantMap>() << event);
> +    event[History::FieldRemoteParticipant] = participants[0].toMap()[History::FieldIdentifier];
> +    writeEvents(QList<QVariantMap>() << event, properties);
> +}
> +
> +void HistoryDaemon::onTextChannelAvailable(const Tp::TextChannelPtr channel)
> +{
> +    // for Rooms we need to explicitly create the thread to allow users to send messages to groups even
> +    // before they receive any message.
> +    // for other types, we can wait until messages are received
> +    if (channel->targetHandleType() == Tp::HandleTypeRoom) {
> +        QString accountId = channel->property(History::FieldAccountId).toString();
> +        QVariantMap properties = propertiesFromChannel(channel);
> +
> +        // first try to fetch the existing thread to see if there is any.
> +        QVariantMap thread = threadForProperties(accountId,
> +                                                 History::EventTypeText,
> +                                                 properties,
> +                                                 matchFlagsForChannel(channel),
> +                                                 false);
> +        if (thread.isEmpty()) {
> +            // if there no existing thread, create one
> +            properties["Requested"] = channel->isRequested();
> +            thread = threadForProperties(accountId,
> +                                         History::EventTypeText,
> +                                         properties,
> +                                         matchFlagsForChannel(channel),
> +                                         true);
> +
> +            // write information event including all initial invitees
> +            Q_FOREACH(const Tp::ContactPtr contact, channel->groupRemotePendingContacts(false)) {
> +                writeInformationEvent(thread, History::InformationTypeInvitationSent, contact->alias());
> +            }
> +
> +            // update participants only if the thread is not available previously. Otherwise we'll wait for membersChanged event
> +            // for reflect in conversation information events for modified participants.
> +            updateRoomParticipants(channel);
> +        }
> +
> +        // write an entry saying you joined the group if 'joined' flag in thread is false and modify that flag.
> +        if (!thread[History::FieldChatRoomInfo].toMap()["Joined"].toBool()) {

All the chat room info properties are like that now. Maybe it would be better to do that in a separate MR to be reviewed separate?

> +            writeInformationEvent(thread, History::InformationTypeSelfJoined);
> +            // update backend
> +            updateRoomProperties(channel, QVariantMap{{"Joined", true}});
> +        }
> +
> +        Tp::AbstractInterface *room_interface = channel->optionalInterface<Tp::Client::ChannelInterfaceRoomInterface>();
> +        Tp::AbstractInterface *room_config_interface = channel->optionalInterface<Tp::Client::ChannelInterfaceRoomConfigInterface>();
> +        Tp::AbstractInterface *subject_interface = channel->optionalInterface<Tp::Client::ChannelInterfaceSubjectInterface>();
> +        ChannelInterfaceRolesInterface *roles_interface = channel->optionalInterface<ChannelInterfaceRolesInterface>();
> +
> +        QList<Tp::AbstractInterface*> interfaces;
> +        interfaces << room_interface << room_config_interface << subject_interface << roles_interface;
> +        for (auto interface : interfaces) {
> +            if (interface) {
> +                interface->setMonitorProperties(true);
> +                interface->setProperty(History::FieldAccountId, accountId);
> +                interface->setProperty(History::FieldThreadId, thread[History::FieldThreadId].toString());
> +                interface->setProperty(History::FieldType, thread[History::FieldType].toInt());
> +                connect(interface, SIGNAL(propertiesChanged(const QVariantMap &,const QStringList &)),
> +                                   SLOT(onRoomPropertiesChanged(const QVariantMap &,const QStringList &)));
> +                // update the stored info
> +                Q_EMIT interface->propertiesChanged(getInterfaceProperties(interface), QStringList());
> +            }
> +        }
> +
> +        connect(channel.data(), SIGNAL(groupMembersChanged(const Tp::Contacts &, const Tp::Contacts &, const Tp::Contacts &, const Tp::Contacts &, const Tp::Channel::GroupMemberChangeDetails &)),
> +                SLOT(onGroupMembersChanged(const Tp::Contacts &, const Tp::Contacts &, const Tp::Contacts &, const Tp::Contacts &, const Tp::Channel::GroupMemberChangeDetails &)));
> +
> +        connect(roles_interface, SIGNAL(RolesChanged(const HandleRolesMap&, const HandleRolesMap&)), SLOT(onRolesChanged(const HandleRolesMap&, const HandleRolesMap&)));
> +    }
> +}
> +
> +void HistoryDaemon::onGroupMembersChanged(const Tp::Contacts &groupMembersAdded,
> +                                          const Tp::Contacts &groupLocalPendingMembersAdded,
> +                                          const Tp::Contacts &groupRemotePendingMembersAdded,
> +                                          const Tp::Contacts &groupMembersRemoved,
> +                                          const Tp::Channel::GroupMemberChangeDetails &details)
> +{
> +    Tp::TextChannelPtr channel(qobject_cast<Tp::TextChannel*>(sender()));
> +
> +    QVariantMap properties;
> +    QVariantMap thread;
> +
> +    // information events for members updates.
> +    bool hasRemotePendingMembersAdded = groupRemotePendingMembersAdded.size() > 0;
> +    bool hasMembersAdded = groupMembersAdded.size() > 0;
> +    bool hasMembersRemoved = groupMembersRemoved.size() > 0;
> +
> +    if (hasRemotePendingMembersAdded || hasMembersAdded || hasMembersRemoved) {
> +        properties = propertiesFromChannel(channel);
> +        thread = threadForProperties(channel->property(History::FieldAccountId).toString(),
> +                                                       History::EventTypeText,
> +                                                       properties,
> +                                                       matchFlagsForChannel(channel),
> +                                                       false);
> +        if (!thread.isEmpty()) {
> +            if (hasRemotePendingMembersAdded) {
> +                Q_FOREACH (const Tp::ContactPtr& contact, groupRemotePendingMembersAdded) {
> +                    if (!foundInThread(contact, thread)) {
> +                        writeInformationEvent(thread, History::InformationTypeInvitationSent, contact->alias());
> +                    }
> +                }
> +            }
> +            if (hasMembersAdded) {
> +                Q_FOREACH (const Tp::ContactPtr& contact, groupMembersAdded) {
> +                    // if this member was not previously regular member in thread, notify about his join
> +                    if (!foundAsMemberInThread(contact, thread)) {
> +                        writeInformationEvent(thread, History::InformationTypeJoined, contact->alias());
> +                    }
> +                }
> +            }
> +
> +            if (hasMembersRemoved) {
> +                if (channel->groupSelfContactRemoveInfo().isValid()) {
> +                    // evaluate if we are leaving by our own or we are kicked
> +                    History::InformationType type = History::InformationTypeSelfLeaving;
> +                    if (channel->groupSelfContactRemoveInfo().hasReason()) {
> +                        switch (channel->groupSelfContactRemoveInfo().reason()) {
> +                        case ChannelGroupChangeReasonKicked:
> +                            type = History::InformationTypeSelfKicked;
> +                            break;
> +                        case ChannelGroupChangeReasonGone:
> +                            type = History::InformationTypeGroupGone;
> +                            break;
> +                        }
> +                    }
> +                    writeInformationEvent(thread, type);
> +                    // update backend
> +                    updateRoomProperties(channel, QVariantMap{{"Joined", false}});
> +                }
> +                else // don't notify any other group member removal if we are leaving the group
> +                {
> +                    Q_FOREACH (const Tp::ContactPtr& contact, groupMembersRemoved) {
> +                        // inform about removed members other than us
> +                        if (contact->id() != channel->groupSelfContact()->id()) {
> +                            writeInformationEvent(thread, History::InformationTypeLeaving, contact->alias());
> +                        }
> +                    }
> +                }
> +            }
> +        }
> +    }
> +
> +    updateRoomParticipants(channel);
> +}
> +
> +void HistoryDaemon::updateRoomParticipants(const Tp::TextChannelPtr channel)
> +{
> +    if (!channel) {
> +        return;
> +    }
> +
> +    QVariantList participants;
> +    QStringList contactsAdded;
> +
> +    ChannelInterfaceRolesInterface *roles_interface = channel->optionalInterface<ChannelInterfaceRolesInterface>();
> +    RolesMap roles;
> +    if (roles_interface) {
> +        roles = roles_interface->getRoles();
> +    }
> +
> +    Q_FOREACH(const Tp::ContactPtr contact, channel->groupRemotePendingContacts(false)) {
> +        QVariantMap participant;
> +        contactsAdded << contact->id();
> +        participant[History::FieldIdentifier] = contact->id();
> +        participant[History::FieldAlias] = contact->alias();
> +        participant[History::FieldParticipantState] = History::ParticipantStateRemotePending;
> +        participant[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
> +        participants << QVariant::fromValue(participant);
> +    }
> +    Q_FOREACH(const Tp::ContactPtr contact, channel->groupLocalPendingContacts(false)) {
> +        QVariantMap participant;
> +        contactsAdded << contact->id();
> +        participant[History::FieldIdentifier] = contact->id();
> +        participant[History::FieldAlias] = contact->alias();
> +        participant[History::FieldParticipantState] = History::ParticipantStateLocalPending;
> +        participant[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
> +        participants << QVariant::fromValue(participant);
> +    }
> +
> +    Q_FOREACH(const Tp::ContactPtr contact, channel->groupContacts(false)) {
> +        // do not include remote and local pending members
> +        if (contactsAdded.contains(contact->id())) {
> +            continue;
> +        }
> +        QVariantMap participant;
> +        participant[History::FieldIdentifier] = contact->id();
> +        participant[History::FieldAlias] = contact->alias();
> +        participant[History::FieldParticipantState] = History::ParticipantStateRegular;
> +        participant[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
> +        participants << QVariant::fromValue(participant);
> +    }
> +
> +    QString accountId = channel->property(History::FieldAccountId).toString();
> +    QString threadId = channel->targetId();
> +    if (mBackend->updateRoomParticipants(accountId, threadId, History::EventTypeText, participants)) {
> +        QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap());
> +        mDBus.notifyThreadsModified(QList<QVariantMap>() << updatedThread);
> +    }
> +}
> +
> +void HistoryDaemon::updateRoomRoles(const Tp::TextChannelPtr &channel, const RolesMap &rolesMap)
> +{
> +    if (!channel) {
> +        return;
> +    }
> +
> +    QVariantMap participantsRoles;
> +
> +    Q_FOREACH(const Tp::ContactPtr contact, channel->groupRemotePendingContacts(false)) {
> +        participantsRoles[contact->id()] = rolesMap[contact->handle().at(0)];
> +    }
> +    Q_FOREACH(const Tp::ContactPtr contact, channel->groupLocalPendingContacts(false)) {
> +        participantsRoles[contact->id()] = rolesMap[contact->handle().at(0)];
> +    }
> +
> +    Q_FOREACH(const Tp::ContactPtr contact, channel->groupContacts(false)) {
> +        if (!participantsRoles.contains(contact->id())) {
> +            participantsRoles[contact->id()] = rolesMap[contact->handle().at(0)];
> +        }
> +    }
> +
> +    // update participants roles
> +    QString accountId = channel->property(History::FieldAccountId).toString();
> +    QString threadId = channel->targetId();
> +    if (mBackend->updateRoomParticipantsRoles(accountId, threadId, History::EventTypeText, participantsRoles)) {
> +        QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap());
> +        mDBus.notifyThreadsModified(QList<QVariantMap>() << updatedThread);
> +    }
> +
> +    // update self roles in room properties
> +    uint selfRoles = rolesMap[channel->groupSelfContact()->handle().at(0)];
> +    updateRoomProperties(channel, QVariantMap{{"SelfRoles", selfRoles}});
> +}
> +
> +void HistoryDaemon::onRoomPropertiesChanged(const QVariantMap &properties,const QStringList &invalidated)
> +{
> +    QString accountId = sender()->property(History::FieldAccountId).toString();
> +    QString threadId = sender()->property(History::FieldThreadId).toString();
> +    History::EventType type = (History::EventType)sender()->property(History::FieldType).toInt();
> +
> +    // get thread before updating to see if there are changes to insert as information events
> +    QVariantMap thread = getSingleThread(type, accountId, threadId, QVariantMap());
> +    if (!thread.empty()) {
> +        writeRoomChangesInformationEvents(thread, properties);
> +    }
> +
> +    updateRoomProperties(accountId, threadId, type, properties, invalidated);
> +}
> +
> +void HistoryDaemon::updateRoomProperties(const Tp::TextChannelPtr &channel, const QVariantMap &properties)
> +{
> +    QString accountId = channel->property(History::FieldAccountId).toString();
> +    QString threadId = channel->targetId();
> +    History::EventType type = History::EventTypeText;
> +    updateRoomProperties(accountId, threadId, type, properties, QStringList());
> +}
> +
> +void HistoryDaemon::updateRoomProperties(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated)
> +{
> +    if (mBackend->updateRoomInfo(accountId, threadId, type, properties, invalidated)) {
> +        QVariantMap thread = getSingleThread(type, accountId, threadId, QVariantMap());
> +        mDBus.notifyThreadsModified(QList<QVariantMap>() << thread);
> +    }
>  }
>  
>  void HistoryDaemon::onMessageReceived(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message)


-- 
https://code.launchpad.net/~phablet-team/history-service/staging/+merge/308933
Your team Ubuntu Phablet Team is subscribed to branch lp:history-service.



More information about the Ubuntu-reviews mailing list