service/ImapMutationCommands.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <QList> | ||
| 4 | #include <QSet> | ||
| 5 | #include <QString> | ||
| 6 | #include <QStringList> | ||
| 7 | |||
| 8 | #include <functional> | ||
| 9 | |||
| 10 | #include "service/ImapResponseParser.h" | ||
| 11 | #include "service/ImapService.h" | ||
| 12 | |||
| 13 | class ImapCommandTable; | ||
| 14 | class ImapPushSession; | ||
| 15 | struct ImapPendingCommand; | ||
| 16 | |||
| 17 | // Mailbox mutations of one IMAP connection (Sprint 92 S92.1.6, extracted | ||
| 18 | // from ImapService): flag STOREs, UID MOVE (single and uid-set, F4.3), the | ||
| 19 | // COPY + STORE \Deleted + EXPUNGE fallback without MOVE, standalone COPY, | ||
| 20 | // EXPUNGE and UID EXPUNGE, and the journal mutation tokens with exactly one | ||
| 21 | // terminal outcome each (Confirmed, Rejected, CancelledBeforeDispatch, | ||
| 22 | // Ambiguous). | ||
| 23 | // | ||
| 24 | // Owner: ImapService (std::unique_ptr), connection thread. Plain class. It | ||
| 25 | // owns the known/dispatched token sets; the state of each MOVE/COPY/STORE | ||
| 26 | // command lives in its pending record (FUNC-08, ImapPendingCommand). The | ||
| 27 | // session state, selected mailbox and capabilities are read by reference; | ||
| 28 | // commands use the command table, push restart and the IDLE check the push | ||
| 29 | // session; every result signal goes through a notifier (the emitter stays | ||
| 30 | // ImapService). | ||
| 31 | class ImapMutationCommands { | ||
| 32 | public: | ||
| 33 | using State = ImapService::State; | ||
| 34 | using MutationOutcome = ImapService::MutationOutcome; | ||
| 35 | |||
| 36 | struct Deps { | ||
| 37 | // ImapService signals. | ||
| 38 | std::function<void()> storeComplete; | ||
| 39 | std::function<void(qint64 token)> mutationDispatched; | ||
| 40 | std::function<void(qint64 token, MutationOutcome outcome, const QString &error, | ||
| 41 | const QString &uidPlusEvidence)> | ||
| 42 | mutationCompleted; | ||
| 43 | std::function<void(qint64 uid, const QString &targetFolder)> messageMoved; | ||
| 44 | std::function<void(const QList<qint64> &uids, const QString &targetFolder)> messagesMoved; | ||
| 45 | std::function<void(qint64 uid, const QString &targetFolder)> messageCopied; | ||
| 46 | std::function<void(const QString &error)> moveError; | ||
| 47 | std::function<void()> expungeComplete; | ||
| 48 | std::function<void(const QString &error)> expungeFailed; | ||
| 49 | std::function<void(const QString &error)> errorOccurred; | ||
| 50 | }; | ||
| 51 | ImapMutationCommands(ImapCommandTable &commands, ImapPushSession &push, | ||
| 52 | const State &state, const QString &selectedFolder, | ||
| 53 | const quint32 &selectedUidValidity, | ||
| 54 | const QStringList &capabilities, Deps deps); | ||
| 55 | |||
| 56 | void markSeen(qint64 uid); | ||
| 57 | void markUnseen(qint64 uid); | ||
| 58 | void storeFlag(qint64 uid, const QString &flag, bool add, qint64 mutationToken = 0); | ||
| 59 | void moveMessage(qint64 uid, const QString &targetFolder, qint64 mutationToken = 0); | ||
| 60 | void moveMessages(const QList<qint64> &uids, const QString &targetFolder, | ||
| 61 | qint64 mutationToken = 0); | ||
| 62 | void moveMessageSet(const QList<qint64> &uids, const QString &targetFolder, | ||
| 63 | const QList<qint64> &mutationTokens); | ||
| 64 | void copyMessage(qint64 uid, const QString &targetFolder, qint64 mutationToken = 0); | ||
| 65 | void expungeUids(const QList<qint64> &uids, const QString &folder, | ||
| 66 | quint32 uidValidity); | ||
| 67 | bool hasUidExpungeCapability() const; | ||
| 68 | void trackMutation(qint64 token); | ||
| 69 | void markMutationDispatched(qint64 token); | ||
| 70 | void completeMutation(qint64 token, MutationOutcome outcome, | ||
| 71 | const QString &error = {}, | ||
| 72 | const QString &uidPlusEvidence = {}); | ||
| 73 | void completeOutstandingMutations(const QString &error); | ||
| 74 | // Tagged completions of the mutation commands. | ||
| 75 | // FUNC-08: `command` is the record of the completing tag (target, UIDs, | ||
| 76 | // journal tokens); the fallback chain hands it on to its next command. | ||
| 77 | void handleTaggedStore(const TaggedResponse &response, ImapPendingCommand &command); | ||
| 78 | void handleTaggedMove(const TaggedResponse &response, ImapPendingCommand &command); | ||
| 79 | void handleTaggedCopy(const TaggedResponse &response, ImapPendingCommand &command); | ||
| 80 | void handleTaggedStoreDelete(const TaggedResponse &response, ImapPendingCommand &command); | ||
| 81 | void handleTaggedExpungeMove(const TaggedResponse &response, ImapPendingCommand &command); | ||
| 82 | void handleTaggedCopyOnly(const TaggedResponse &response, ImapPendingCommand &command); | ||
| 83 | void handleTaggedExpunge(const TaggedResponse &response); | ||
| 84 | |||
| 85 | // Journal tokens shared with the test contract (single owner: this unit). | ||
| 86 | 1 | QSet<qint64> &knownMutationTokens() { return m_knownMutationTokens; } | |
| 87 | |||
| 88 | private: | ||
| 89 | // F4.3: complete every token of a MOVE/COPY record with one outcome. | ||
| 90 | void completePendingMoveMutations(const ImapPendingCommand &command, | ||
| 91 | MutationOutcome outcome, const QString &error, | ||
| 92 | const QString &uidPlusEvidence = {}); | ||
| 93 | |||
| 94 | ImapCommandTable &m_commands; | ||
| 95 | ImapPushSession &m_push; | ||
| 96 | const State &m_state; // ImapService::m_state | ||
| 97 | const QString &m_selectedFolder; // ImapService::m_selectedFolder | ||
| 98 | const quint32 &m_selectedUidValidity; // ImapService::m_selectedUidValidity | ||
| 99 | const QStringList &m_capabilities; // ImapService::m_capabilities | ||
| 100 | Deps m_deps; | ||
| 101 | |||
| 102 | QSet<qint64> m_knownMutationTokens; | ||
| 103 | QSet<qint64> m_dispatchedMutationTokens; | ||
| 104 | }; | ||
| 105 |