Serenity Operating System
1/*
2 * Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
3 * Copyright (c) 2022, the SerenityOS developers.
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#include "AccountHolder.h"
9
10AccountHolder::AccountHolder()
11{
12 m_mailbox_tree_model = MailboxTreeModel::create(*this);
13}
14
15void AccountHolder::add_account_with_name_and_mailboxes(DeprecatedString name, Vector<IMAP::ListItem> const& mailboxes)
16{
17 auto account = AccountNode::create(move(name));
18
19 // This holds all of the ancestors of the current leaf folder.
20 Vector<NonnullRefPtr<MailboxNode>> folder_stack;
21
22 for (auto& mailbox : mailboxes) {
23 // mailbox.name is converted to StringView to get access to split by string.
24 auto subfolders = StringView(mailbox.name).split_view(mailbox.reference);
25
26 // Use the last part of the path as the display name.
27 // For example: "[Mail]/Subfolder" will be displayed as "Subfolder"
28 auto mailbox_node = MailboxNode::create(account, mailbox, subfolders.last());
29
30 if (subfolders.size() > 1) {
31 VERIFY(!folder_stack.is_empty());
32
33 // This gets the parent folder of the leaf folder that we just created above.
34 // For example, with "[Mail]/Subfolder/Leaf", "subfolders" will have three items:
35 // - "[Mail]" at index 0.
36 // - "Subfolder" at index 1. This is the parent folder of the leaf folder.
37 // - "Leaf" at index 2. This is the leaf folder.
38 // Notice that the parent folder is always two below the size of "subfolders".
39 // This assumes that there was two listings before this, in this exact order:
40 // 1. "[Mail]"
41 // 2. "[Mail]/Subfolder"
42 auto& parent_folder = folder_stack.at(subfolders.size() - 2);
43
44 // Only keep the ancestors of the current leaf folder.
45 folder_stack.shrink(subfolders.size() - 1);
46
47 parent_folder->add_child(mailbox_node);
48 VERIFY(!mailbox_node->has_parent());
49 mailbox_node->set_parent(parent_folder);
50
51 // FIXME: This assumes that the server has the "CHILDREN" capability.
52 if (mailbox.flags & (unsigned)IMAP::MailboxFlag::HasChildren)
53 folder_stack.append(mailbox_node);
54 } else {
55 // FIXME: This assumes that the server has the "CHILDREN" capability.
56 if (mailbox.flags & (unsigned)IMAP::MailboxFlag::HasChildren) {
57 if (!folder_stack.is_empty() && folder_stack.first()->select_name() != mailbox.name) {
58 // This is a new root folder, clear the stack as there are no ancestors of the current leaf folder at this point.
59 folder_stack.clear();
60 }
61
62 folder_stack.append(mailbox_node);
63 }
64
65 account->add_mailbox(move(mailbox_node));
66 }
67 }
68
69 m_accounts.append(move(account));
70 rebuild_tree();
71}
72
73void AccountHolder::rebuild_tree()
74{
75 m_mailbox_tree_model->invalidate();
76}