Skip to content

Commit

Permalink
Merge pull request #3147 from dehnhardt/FolderTree
Browse files Browse the repository at this point in the history
Multilevel mailbox structure
  • Loading branch information
ChristophWurst authored Sep 1, 2020
2 parents 00ade2c + 9d1365e commit 9971143
Show file tree
Hide file tree
Showing 17 changed files with 777 additions and 477 deletions.
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
- **🙈 We’re not reinventing the wheel!** Based on the great [Horde](http://horde.org) libraries.
- **📬 Want to host your own mail server?** We don’t have to reimplement this as you could set up [Mail-in-a-Box](https://mailinabox.email)!
]]></description>
<version>1.5.0-alpha2</version>
<version>1.5.0-alpha3</version>
<licence>agpl</licence>
<author>Christoph Wurst</author>
<author>Roeland Jago Douma</author>
Expand Down
5 changes: 5 additions & 0 deletions lib/Db/MailAccount.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@
* @method void setOrder(int $order)
* @method bool getShowSubscribedOnly()
* @method void setShowSubscribedOnly(bool $showSubscribedOnly)
* @method string|null getPersonalNamespace()
* @method void setPersonalNamespace(string|null $personalNamespace)
*/
class MailAccount extends Entity {
protected $userId;
Expand All @@ -90,6 +92,7 @@ class MailAccount extends Entity {
protected $provisioned;
protected $order;
protected $showSubscribedOnly;
protected $personalNamespace;

/**
* @param array $params
Expand Down Expand Up @@ -146,6 +149,7 @@ public function __construct(array $params=[]) {
$this->addType('provisioned', 'bool');
$this->addType('order', 'integer');
$this->addType('showSubscribedOnly', 'boolean');
$this->addType('personalNamespace', 'string');
}

/**
Expand All @@ -166,6 +170,7 @@ public function toJson() {
'editorMode' => $this->getEditorMode(),
'provisioned' => $this->getProvisioned(),
'showSubscribedOnly' => $this->getShowSubscribedOnly(),
'personalNamespace' => $this->getPersonalNamespace(),
];

if (!is_null($this->getOutboundHost())) {
Expand Down
23 changes: 23 additions & 0 deletions lib/IMAP/MailboxSync.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@

namespace OCA\Mail\IMAP;

use Horde_Imap_Client;
use Horde_Imap_Client_Data_Namespace;
use Horde_Imap_Client_Exception;
use Horde_Imap_Client_Namespace_List;
use OCA\Mail\Exception\ServiceException;
use function in_array;
use function json_encode;
Expand Down Expand Up @@ -81,6 +84,16 @@ public function sync(Account $account, bool $force = false): void {
}

$client = $this->imapClientFactory->getClient($account);
try {
$namespaces = $client->getNamespaces([], [
'ob_return' => true,
]);
$account->getMailAccount()->setPersonalNamespace(
$this->getPersonalNamespace($namespaces)
);
} catch (Horde_Imap_Client_Exception $e) {
$this->logger->debug('Getting namespaces for account ' . $account->getId() . ' failed: ' . $e->getMessage());
}

try {
$folders = $this->folderMapper->getFolders($account, $client);
Expand Down Expand Up @@ -125,6 +138,16 @@ private function persist(Account $account, array $folders, array $existing): voi
$this->mailAccountMapper->update($account->getMailAccount());
}

private function getPersonalNamespace(Horde_Imap_Client_Namespace_List $namespaces): ?string {
foreach ($namespaces as $namespace) {
/** @var Horde_Imap_Client_Data_Namespace $namespace */
if ($namespace->type === Horde_Imap_Client::NS_PERSONAL) {
return $namespace->name;
}
}
return null;
}

private function updateMailboxFromFolder(Folder $folder, Mailbox $mailbox): void {
$mailbox->setDelimiter($folder->getDelimiter());
$mailbox->setAttributes(json_encode($folder->getAttributes()));
Expand Down
31 changes: 31 additions & 0 deletions lib/Migration/Version1050Date20200831124954.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace OCA\Mail\Migration;

use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;

class Version1050Date20200831124954 extends SimpleMigrationStep {

/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
* @return ISchemaWrapper
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();

$accountsTable = $schema->getTable('mail_accounts');
$accountsTable->addColumn('personal_namespace', 'string', [
'notnull' => false,
]);

return $schema;
}
}
5 changes: 4 additions & 1 deletion src/components/NavigationMailbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
@click="clearCache">
{{ t('mail', 'Clear locally cached data, in case there are issues with synchronization.') }}
</ActionButton>
<ActionButton v-if="!account.isUnified && !mailbox.specialRole" icon="icon-delete" @click="deleteMailbox">
<ActionButton v-if="!account.isUnified && !mailbox.specialRole && !hasSubMailboxes" icon="icon-delete" @click="deleteMailbox">
{{ t('mail', 'Delete folder') }}
</ActionButton>
</template>
Expand Down Expand Up @@ -176,6 +176,9 @@ export default {
},
}
},
hasSubMailboxes() {
return this.subMailboxes.length > 0
},
subMailboxes() {
return this.$store.getters.getSubMailboxes(this.mailbox.databaseId)
},
Expand Down
62 changes: 0 additions & 62 deletions src/imap/MailboxHierarchy.js

This file was deleted.

34 changes: 0 additions & 34 deletions src/imap/MailboxPrefix.js

This file was deleted.

8 changes: 6 additions & 2 deletions src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,14 @@ export default {
commit('removeMailbox', { id: mailbox.databaseId })
},
async createMailbox({ commit }, { account, name }) {
const mailbox = await createMailbox(account.id, name)
console.debug(`mailbox ${name} created for account ${account.id}`, { mailbox })
const prefixed = (account.personalNamespace && !name.startsWith(account.personalNamespace))
? account.personalNamespace + name
: name
const mailbox = await createMailbox(account.id, prefixed)
console.debug(`mailbox ${prefixed} created for account ${account.id}`, { mailbox })
commit('addMailbox', { account, mailbox })
commit('expandAccount', account.id)
return mailbox
},
moveAccount({ commit, getters }, { account, up }) {
const accounts = getters.accounts
Expand Down
1 change: 0 additions & 1 deletion src/store/getters.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export const getters = {
},
getSubMailboxes: (state, getters) => (id) => {
const mailbox = getters.getMailbox(id)

return mailbox.mailboxes.map((id) => state.mailboxes[id])
},
getUnifiedMailbox: (state) => (specialRole) => {
Expand Down
4 changes: 4 additions & 0 deletions src/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,27 @@ export default new Vuex.Store({
accountId: 0,
attributes: ['\\subscribed'],
isUnified: true,
path: '',
specialUse: ['inbox'],
specialRole: 'inbox',
unread: 0,
mailboxes: [],
envelopeLists: {},
name: 'UNIFIED INBOX',
},
[PRIORITY_INBOX_ID]: {
id: PRIORITY_INBOX_ID,
databaseId: PRIORITY_INBOX_ID,
accountId: 0,
attributes: ['\\subscribed'],
isPriorityInbox: true,
path: '',
specialUse: ['inbox'],
specialRole: 'inbox',
unread: 0,
mailboxes: [],
envelopeLists: {},
name: 'PRIORITY INBOX',
},
},
envelopes: {},
Expand Down
Loading

0 comments on commit 9971143

Please sign in to comment.