presentation/QuickInvitation.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include "data/ImipInvitation.h" | ||
| 4 | #include "data/MailRequest.h" | ||
| 5 | |||
| 6 | #include <QObject> | ||
| 7 | #include <QVariantList> | ||
| 8 | #include <QVariantMap> | ||
| 9 | #include <functional> | ||
| 10 | #include <optional> | ||
| 11 | |||
| 12 | class MailSessionCore; | ||
| 13 | |||
| 14 | // Sprint 93 S93.5.2 (CAL-IMIP, D-3): the invitation card of the displayed | ||
| 15 | // mail. QML reaches it as `backend.invitation`. | ||
| 16 | // | ||
| 17 | // The host reports the displayed mail and its attachments (setMail). The | ||
| 18 | // first text/calendar or .ics attachment is read (bounded window) and | ||
| 19 | // parsed; `card` then describes it for InvitationCard.qml: | ||
| 20 | // method, state, title, whenText, zoneText, location, meetingUrl, | ||
| 21 | // organizer, attendees [{name, email, status, me}], rrule, startIso, | ||
| 22 | // dateIso, conflicts [text], changes [field], myStatus, inCalendar, | ||
| 23 | // calendarName, canReply, replyAs, serverSends, comment, replier, | ||
| 24 | // replierStatus, calendars [{key, displayName, color}], defaultCalendar. | ||
| 25 | // state: "new" (not stored yet), "answered", "updated" (newer SEQUENCE than | ||
| 26 | // the stored copy), "outdated" (older), "cancelled", "reply" (an attendee | ||
| 27 | // answered an own appointment), "counter" (display only), "publish" (a | ||
| 28 | // calendar file without attendees to answer). | ||
| 29 | // | ||
| 30 | // Answers store the invitation through the CalendarSyncCoordinator (the raw | ||
| 31 | // resource, so nothing is lost) with the user's PARTSTAT and send the iMIP | ||
| 32 | // REPLY from the active account — unless the DAV server schedules | ||
| 33 | // (RFC 6638 schedule-outbox-URL discovered, or the "server sends replies" | ||
| 34 | // setting), which then sends the reply itself. | ||
| 35 | class QuickInvitation final : public QObject { | ||
| 36 | 135 | Q_OBJECT | |
| 37 | Q_PROPERTY(bool active READ active NOTIFY changed) | ||
| 38 | Q_PROPERTY(QVariantMap card READ card NOTIFY changed) | ||
| 39 | // Who answers invitations: "auto", "client" or "server" (see below). | ||
| 40 | Q_PROPERTY(QString replyMode READ replyMode WRITE setReplyMode NOTIFY changed) | ||
| 41 | public: | ||
| 42 | struct Deps { | ||
| 43 | std::function<QVariantList()> calendarChoices; // QuickPimBackend::calendarChoices | ||
| 44 | std::function<QString()> lastCalendar; // "accountId\npath" | ||
| 45 | std::function<bool(const QStringList &recipients, const QByteArray &message, | ||
| 46 | const QString &doneText)> send; | ||
| 47 | std::function<void(const QString &)> setStatus; | ||
| 48 | }; | ||
| 49 | QuickInvitation(MailSessionCore &session, Deps deps, QObject *parent = nullptr); | ||
| 50 | |||
| 51 | 1565 | bool active() const { return m_invitation.has_value(); } | |
| 52 | 47 | QVariantMap card() const { return m_card; } | |
| 53 | |||
| 54 | // The displayed mail changed or its attachments arrived. Cheap when | ||
| 55 | // nothing changed (same mail and attachment). | ||
| 56 | void setMail(const MailId &mail, const QVariantList &attachments, const QString &from = {}); | ||
| 57 | // Shows calendar text directly (tests, the bytes of setMail's read). | ||
| 58 | void showCalendarText(const QString &text); | ||
| 59 | |||
| 60 | // partstat: ACCEPTED, TENTATIVE or DECLINED. calendarKey from | ||
| 61 | // card.calendars ("" = card.defaultCalendar); the stored copy's calendar | ||
| 62 | // wins for an invitation that is already in the calendar. | ||
| 63 | Q_INVOKABLE bool respond(const QString &partstat, const QString &calendarKey, | ||
| 64 | const QString &comment, bool confirmMismatch = false); | ||
| 65 | // PUBLISH / an update without a new answer: store as is. | ||
| 66 | Q_INVOKABLE bool addToCalendar(const QString &calendarKey, bool confirmMismatch = false); | ||
| 67 | // CANCEL: removes the stored appointment. | ||
| 68 | Q_INVOKABLE bool removeFromCalendar(bool confirmMismatch = false); | ||
| 69 | // REPLY: stores the attendee's new status in the own appointment. | ||
| 70 | Q_INVOKABLE bool applyReply(bool confirmMismatch = false); | ||
| 71 | |||
| 72 | // "auto" (server decides by its scheduling support), "client" (MailJD | ||
| 73 | // always sends replies) or "server" (never sends replies); QSettings | ||
| 74 | // "calendar/imipReplies". | ||
| 75 | QString replyMode() const; | ||
| 76 | void setReplyMode(const QString &mode); | ||
| 77 | |||
| 78 | signals: | ||
| 79 | void changed(); | ||
| 80 | |||
| 81 | private: | ||
| 82 | struct Stored { | ||
| 83 | QString accountId, calendarPath; | ||
| 84 | CalendarEvent master; | ||
| 85 | }; | ||
| 86 | std::optional<Stored> storedCopy() const; | ||
| 87 | QStringList ownAddresses() const; | ||
| 88 | QString ownAddress() const; // the attendee address the user answers as | ||
| 89 | bool serverSends(const QString &accountId) const; | ||
| 90 | bool resolveCalendar(const QString &key, QString *accountId, QString *path) const; | ||
| 91 | QStringList conflicts() const; | ||
| 92 | QVariantList attendeeList(const QString &me) const; | ||
| 93 | void rebuildCard(); | ||
| 94 | void clear(); | ||
| 95 | bool storeRows(const QString &accountId, const QString &path, const QString &partstat); | ||
| 96 | bool admitsMutation(bool confirmMismatch); | ||
| 97 | |||
| 98 | MailSessionCore &m_session; | ||
| 99 | Deps m_deps; | ||
| 100 | MailId m_mail; | ||
| 101 | qint64 m_attachmentId = 0; | ||
| 102 | quint64 m_readGeneration = 0; | ||
| 103 | std::optional<Imip::Invitation> m_invitation; | ||
| 104 | QVariantMap m_card; | ||
| 105 | QString m_mailFrom; | ||
| 106 | QString m_mailSender; | ||
| 107 | bool m_replyAutoApplied = false; // S108.8.7: this card's REPLY was applied without a click | ||
| 108 | void applyReplyAutomatically(); | ||
| 109 | }; | ||
| 110 |