diff --git a/lib/Contracts/IMailManager.php b/lib/Contracts/IMailManager.php
index 9c470412b3..e3b4b6a5bf 100644
--- a/lib/Contracts/IMailManager.php
+++ b/lib/Contracts/IMailManager.php
@@ -196,4 +196,17 @@ public function renameMailbox(Account $account, Mailbox $mailbox, string $name):
* @throws ServiceException
*/
public function deleteMailbox(Account $account, Mailbox $mailbox): void;
+
+ /**
+ * @param Account $account
+ * @param string $mailbox
+ * @param bool $subscribed
+ *
+ * @return Mailbox
+ * @throws ClientException
+ * @throws ServiceException
+ */
+ public function updateSubscription(Account $account,
+ Mailbox $mailbox,
+ bool $subscribed): Mailbox;
}
diff --git a/lib/Controller/MailboxesController.php b/lib/Controller/MailboxesController.php
index 4a37192856..b70c66d707 100644
--- a/lib/Controller/MailboxesController.php
+++ b/lib/Controller/MailboxesController.php
@@ -108,7 +108,8 @@ public function index(int $accountId): JSONResponse {
* @return JSONResponse
*/
public function patch(int $id,
- ?string $name = null): JSONResponse {
+ ?string $name = null,
+ ?bool $subscribed = null): JSONResponse {
$mailbox = $this->mailManager->getMailbox($this->currentUserId, $id);
$account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
@@ -119,6 +120,13 @@ public function patch(int $id,
$name
);
}
+ if ($subscribed !== null) {
+ $mailbox = $this->mailManager->updateSubscription(
+ $account,
+ $mailbox,
+ $subscribed
+ );
+ }
return new JSONResponse($mailbox);
}
diff --git a/lib/Service/MailManager.php b/lib/Service/MailManager.php
index 7d417bec5a..a78fde53f4 100644
--- a/lib/Service/MailManager.php
+++ b/lib/Service/MailManager.php
@@ -310,6 +310,28 @@ public function markFolderAsRead(Account $account, Mailbox $mailbox): void {
$this->imapMessageMapper->markAllRead($client, $mailbox->getName());
}
+ public function updateSubscription(Account $account, Mailbox $mailbox, bool $subscribed): Mailbox {
+ /**
+ * 1. Change subscription on IMAP
+ */
+ $client = $this->imapClientFactory->getClient($account);
+ try {
+ $client->subscribeMailbox($mailbox->getName(), $subscribed);
+ } catch (Horde_Imap_Client_Exception $e) {
+ throw new ServiceException("Could not set subscription status for mailbox $mailbox on IMAP: " . $e->getMessage(), $e->getCode(), $e);
+ }
+
+ /**
+ * 2. Pull changes into the mailbox database cache
+ */
+ $this->mailboxSync->sync($account, true);
+
+ /**
+ * 3. Return the updated object
+ */
+ return $this->mailboxMapper->find($account, $mailbox->getName());
+ }
+
public function flagMessage(Account $account, string $mailbox, int $uid, string $flag, bool $value): void {
$client = $this->imapClientFactory->getClient($account);
try {
diff --git a/src/components/NavigationMailbox.vue b/src/components/NavigationMailbox.vue
index 49c07416e2..82354408a2 100644
--- a/src/components/NavigationMailbox.vue
+++ b/src/components/NavigationMailbox.vue
@@ -80,6 +80,15 @@
@click="clearCache">
{{ t('mail', 'Clear locally cached data, in case there are issues with synchronization.') }}
+
+
+ {{ t('mail', 'Subscribed') }}
+
+
{{ t('mail', 'Delete folder') }}
@@ -103,6 +112,7 @@
import AppNavigationItem from '@nextcloud/vue/dist/Components/AppNavigationItem'
import AppNavigationCounter from '@nextcloud/vue/dist/Components/AppNavigationCounter'
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
+import ActionCheckbox from '@nextcloud/vue/dist/Components/ActionCheckbox'
import ActionInput from '@nextcloud/vue/dist/Components/ActionInput'
import ActionText from '@nextcloud/vue/dist/Components/ActionText'
@@ -120,6 +130,7 @@ export default {
AppNavigationCounter,
ActionText,
ActionButton,
+ ActionCheckbox,
ActionInput,
},
props: {
@@ -148,6 +159,7 @@ export default {
loadingMarkAsRead: false,
clearingCache: false,
showSaving: false,
+ changeSubscription: false,
editing: false,
showSubMailboxes: false,
menuOpen: false,
@@ -164,6 +176,9 @@ export default {
|| (this.mailbox.attributes && this.mailbox.attributes.includes('\\subscribed'))
)
},
+ notVirtual() {
+ return !this.account.isUnified && this.mailbox.specialRole !== 'flagged'
+ },
title() {
if (this.filter === 'starred') {
// Little hack to trick the translation logic into a different path
@@ -218,6 +233,9 @@ export default {
}
return t('mail', 'Loading …')
},
+ isSubscribed() {
+ return this.mailbox.attributes && this.mailbox.attributes.includes('\\subscribed')
+ },
},
methods: {
/**
@@ -295,6 +313,21 @@ export default {
.catch((error) => logger.error(`could not mark mailbox ${this.mailbox.databaseId} as read`, { error }))
.then(() => (this.loadingMarkAsRead = false))
},
+ async changeFolderSubscription(subscribed) {
+ try {
+ this.changeSubscription = true
+
+ await this.$store.dispatch('changeMailboxSubscription', {
+ mailbox: this.mailbox,
+ subscribed,
+ })
+ } catch (error) {
+ logger.error(`could not update subscription of mailbox ${mailbox.databaseId}`, { error })
+ throw error
+ } finally {
+ this.changeSubscription = false
+ }
+ },
async clearCache() {
try {
this.clearingCache = true
diff --git a/src/store/actions.js b/src/store/actions.js
index 629cbca83a..76da406e66 100644
--- a/src/store/actions.js
+++ b/src/store/actions.js
@@ -212,6 +212,21 @@ export default {
})
)
},
+ async changeMailboxSubscription({ commit }, { mailbox, subscribed }) {
+ logger.debug(`toggle subscription for mailbox ${mailbox.databaseId}`, {
+ mailbox,
+ subscribed,
+ })
+ const updated = await patchMailbox(mailbox.databaseId, { subscribed })
+
+ commit('updateMailbox', {
+ mailbox: updated,
+ })
+ logger.debug(`subscription for mailbox ${mailbox.databaseId} updated`, {
+ mailbox,
+ updated,
+ })
+ },
fetchEnvelope({ commit, getters }, id) {
const cached = getters.getEnvelope(id)
if (cached) {
diff --git a/src/store/mutations.js b/src/store/mutations.js
index abfa075cad..0e893d0f9f 100644
--- a/src/store/mutations.js
+++ b/src/store/mutations.js
@@ -113,6 +113,9 @@ export default {
addMailbox(state, { account, mailbox }) {
addMailboxToState(state, account, mailbox)
},
+ updateMailbox(state, { mailbox }) {
+ Vue.set(state.mailboxes, mailbox.databaseId, mailbox)
+ },
removeMailbox(state, { id }) {
const mailbox = state.mailboxes[id]
if (mailbox === undefined) {