Skip to content

Commit

Permalink
add sorting capabilities to mail
Browse files Browse the repository at this point in the history
Signed-off-by: hamza221 <[email protected]>
  • Loading branch information
hamza221 committed Jul 21, 2023
1 parent 69d8952 commit 625dd2b
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 24 deletions.
10 changes: 6 additions & 4 deletions lib/Contracts/IMailSearch.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public function findMessage(Account $account,
/**
* @param Account $account
* @param Mailbox $mailbox
* @param string $sortOrder
* @param string|null $filter
* @param int|null $cursor
* @param int|null $limit
Expand All @@ -56,10 +57,11 @@ public function findMessage(Account $account,
* @throws ServiceException
*/
public function findMessages(Account $account,
Mailbox $mailbox,
?string $filter,
?int $cursor,
?int $limit): array;
Mailbox $mailbox,
string $sortOrder,
?string $filter,
?int $cursor,
?int $limit): array;

/**
* @param IUser $user
Expand Down
10 changes: 8 additions & 2 deletions lib/Controller/MessagesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
use OCA\Mail\Contracts\IMailSearch;
use OCA\Mail\Contracts\IMailTransmission;
use OCA\Mail\Contracts\ITrustedSenderService;
use OCA\Mail\Contracts\IUserPreferences;
use OCA\Mail\Db\Message;
use OCA\Mail\Exception\ClientException;
use OCA\Mail\Exception\ServiceException;
Expand Down Expand Up @@ -86,6 +87,7 @@ class MessagesController extends Controller {
private SmimeService $smimeService;
private IMAPClientFactory $clientFactory;
private IDkimService $dkimService;
private IUserPreferences $preferences;

public function __construct(string $appName,
IRequest $request,
Expand All @@ -104,7 +106,8 @@ public function __construct(string $appName,
IMailTransmission $mailTransmission,
SmimeService $smimeService,
IMAPClientFactory $clientFactory,
IDkimService $dkimService) {
IDkimService $dkimService,
IUserPreferences $preferences) {
parent::__construct($appName, $request);
$this->accountService = $accountService;
$this->mailManager = $mailManager;
Expand All @@ -122,6 +125,7 @@ public function __construct(string $appName,
$this->smimeService = $smimeService;
$this->clientFactory = $clientFactory;
$this->dkimService = $dkimService;
$this->preferences = $preferences;
}

/**
Expand Down Expand Up @@ -149,12 +153,14 @@ public function index(int $mailboxId,
return new JSONResponse([], Http::STATUS_FORBIDDEN);
}

$this->logger->debug("loading messages of folder <$mailboxId>");
$this->logger->debug("loading messages of mailbox <$mailboxId>");

$order = $this->preferences->getPreference($this->currentUserId, 'sort-order', 'newest') === 'newest' ? 'DESC': 'ASC';
return new JSONResponse(
$this->mailSearch->findMessages(
$account,
$mailbox,
$order,
$filter === '' ? null : $filter,
$cursor,
$limit
Expand Down
5 changes: 5 additions & 0 deletions lib/Controller/PageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@ public function index(): TemplateResponse {
$this->tagMapper->getAllTagsForUser($this->currentUserId)
);

$this->initialStateService->provideInitialState(
'sort-order',
$this->preferences->getPreference($this->currentUserId, 'sort-order', 'newest')
);

try {
$password = $this->credentialStore->getLoginCredentials()->getPassword();
$passwordIsUnavailable = $password === null || $password === '';
Expand Down
15 changes: 10 additions & 5 deletions lib/Db/MessageMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -695,11 +695,11 @@ public function findByMessageId(Account $account, string $messageId): array {
* @param Mailbox $mailbox
* @param SearchQuery $query
* @param int|null $limit
* @param int[]|null $uids
* @param int[]|null $uidsa
*
* @return int[]
*/
public function findIdsByQuery(Mailbox $mailbox, SearchQuery $query, ?int $limit, array $uids = null): array {
public function findIdsByQuery(Mailbox $mailbox, SearchQuery $query, string $sortOrder, ?int $limit, array $uids = null): array {
$qb = $this->db->getQueryBuilder();

if ($this->needDistinct($query)) {
Expand Down Expand Up @@ -820,7 +820,11 @@ public function findIdsByQuery(Mailbox $mailbox, SearchQuery $query, ?int $limit

$select->andWhere($qb->expr()->isNull('m2.id'));

$select->orderBy('m.sent_at', 'desc');
if ($sortOrder === 'ASC') {
$select->orderBy('sent_at', $sortOrder);
} else {
$select->orderBy('sent_at', 'DESC');
}

if ($limit !== null) {
$select->setMaxResults($limit);
Expand Down Expand Up @@ -1074,10 +1078,11 @@ public function findByMailboxAndIds(Mailbox $mailbox, string $userId, array $ids
/**
* @param string $userId
* @param int[] $ids
* @param string $sortOrder
*
* @return Message[]
*/
public function findByIds(string $userId, array $ids): array {
public function findByIds(string $userId, array $ids, string $sortOrder): array {
if ($ids === []) {
return [];
}
Expand All @@ -1088,7 +1093,7 @@ public function findByIds(string $userId, array $ids): array {
->where(
$qb->expr()->in('id', $qb->createParameter('ids'))
)
->orderBy('sent_at', 'desc');
->orderBy('sent_at', $sortOrder);

$results = [];
foreach (array_chunk($ids, 1000) as $chunk) {
Expand Down
11 changes: 7 additions & 4 deletions lib/Service/Search/MailSearch.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public function findMessage(Account $account,
/**
* @param Account $account
* @param Mailbox $mailbox
* @param string $sortOrder
* @param string|null $filter
* @param int|null $cursor
* @param int|null $limit
Expand All @@ -103,6 +104,7 @@ public function findMessage(Account $account,
*/
public function findMessages(Account $account,
Mailbox $mailbox,
string $sortOrder,
?string $filter,
?int $cursor,
?int $limit): array {
Expand Down Expand Up @@ -130,7 +132,8 @@ public function findMessages(Account $account,
$account,
$mailbox,
$this->messageMapper->findByIds($account->getUserId(),
$this->getIdsLocally($account, $mailbox, $query, $limit)
$this->getIdsLocally($account, $mailbox, $query, $sortOrder, $limit),
$sortOrder,
)
);
}
Expand Down Expand Up @@ -164,17 +167,17 @@ public function findMessagesGlobally(IUser $user,
*
* @throws ServiceException
*/
private function getIdsLocally(Account $account, Mailbox $mailbox, SearchQuery $query, ?int $limit): array {
private function getIdsLocally(Account $account, Mailbox $mailbox, SearchQuery $query, string $sortOrder, ?int $limit): array {
if (empty($query->getTextTokens())) {
return $this->messageMapper->findIdsByQuery($mailbox, $query, $limit);
return $this->messageMapper->findIdsByQuery($mailbox, $query, $sortOrder, $limit);
}

$fromImap = $this->imapSearchProvider->findMatches(
$account,
$mailbox,
$query
);
return $this->messageMapper->findIdsByQuery($mailbox, $query, $limit, $fromImap);
return $this->messageMapper->findIdsByQuery($mailbox, $query, $sortOrder, $limit, $fromImap);
}

/**
Expand Down
60 changes: 59 additions & 1 deletion src/components/AppSettingsMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,33 @@
</ButtonVue>
<SmimeCertificateModal v-if="displaySmimeCertificateModal"
@close="displaySmimeCertificateModal = false" />
<h2 class="section-title">
Sorting
</h2>
<div class="sorting">
<CheckboxRadioSwitch
class="sorting__switch"
:button-variant="true"
:checked="sortOrder"
value="newest"
name="order_radio"
type="radio"
button-variant-grouped="horizontal"
@update:checked="onSortByDate">
{{ t('mail', 'Newest') }}
</CheckboxRadioSwitch>
<CheckboxRadioSwitch
class="sorting__switch"
:button-variant="true"
:checked="sortOrder"
value="oldest"
name="order_radio"
type="radio"
button-variant-grouped="horizontal"
@update:checked="onSortByDate">
{{ t('mail', 'Oldest') }}
</CheckboxRadioSwitch>
</div>

<p class="mailvelope-section">
{{ t('mail', 'Looking for a way to encrypt your emails?') }}
Expand All @@ -116,7 +143,7 @@
import { generateUrl } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs'
import { NcButton as ButtonVue, NcLoadingIcon as IconLoading } from '@nextcloud/vue'
import { NcButton as ButtonVue, NcLoadingIcon as IconLoading, NcCheckboxRadioSwitch as CheckboxRadioSwitch } from '@nextcloud/vue'
import IconInfo from 'vue-material-design-icons/Information'
import IconAdd from 'vue-material-design-icons/Plus'
Expand All @@ -137,6 +164,7 @@ export default {
IconLoading,
IconLock,
SmimeCertificateModal,
CheckboxRadioSwitch,
},
data() {
return {
Expand All @@ -152,6 +180,7 @@ export default {
autoTaggingText: t('mail', 'Automatically classify importance of new email'),
toggleAutoTagging: false,
displaySmimeCertificateModal: false,
sortOrder: 'newest',
}
},
computed: {
Expand All @@ -171,6 +200,9 @@ export default {
return this.$store.getters.getPreference('allow-new-accounts', true)
},
},
mounted() {
this.sortOrder = this.$store.getters.getPreference('sort-order', 'newest')
},
methods: {
onToggleButtonReplies(e) {
this.loadingReplySettings = true
Expand Down Expand Up @@ -211,6 +243,21 @@ export default {
this.loadingOptOutSettings = false
})
},
async onSortByDate(e) {
const previousValue = this.sortOrder
try {
this.sortOrder = e
await this.$store
.dispatch('savePreference', {
key: 'sort-order',
value: e,
})
} catch (error) {
Logger.error('could not save preferences', { error })
this.sortOrder = previousValue
showError(t('mail', 'Could not update preference'))
}
},
async onToggleAutoTagging(e) {
this.toggleAutoTagging = true
Expand Down Expand Up @@ -307,4 +354,15 @@ p.app-settings {
}
}
.section-title {
margin-top: 20px;
margin-bottom: 10px;
}
.sorting {
display: flex;
width: 100%;
&__switch{
width: 50%;
}
}
</style>
28 changes: 20 additions & 8 deletions src/components/EnvelopeList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@
</transition>
<transition-group name="list">
<Envelope
v-for="(env, index) in envelopes"
v-for="(env, index) in sortedEnvelops"
:key="env.databaseId"
:data="env"
:mailbox="mailbox"
Expand Down Expand Up @@ -278,6 +278,18 @@ export default {
}
},
computed: {
sortOrder() {
return this.$store.getters.getPreference('sort-order', 'newest')
},
sortedEnvelops() {
if (this.sortOrder === 'oldest') {
return [...this.envelopes].sort((a, b) => {
return a.dateInt < b.dateInt ? -1 : 1
})
}
return [...this.envelopes]
},
selectMode() {
// returns true when in selection mode (where the user selects several emails at once)
return this.selection.length > 0
Expand Down Expand Up @@ -307,15 +319,15 @@ export default {
return this.selectedEnvelopes.every((env) => env.flags.flagged === true)
},
selectedEnvelopes() {
return this.envelopes.filter((env) => this.selection.includes(env.databaseId))
return this.sortedEnvelops.filter((env) => this.selection.includes(env.databaseId))
},
hasMultipleAccounts() {
const mailboxIds = this.envelopes.map(envelope => envelope.mailboxId)
const mailboxIds = this.sortedEnvelops.map(envelope => envelope.mailboxId)
return Array.from(new Set(mailboxIds)).length > 1
},
},
watch: {
envelopes(newVal, oldVal) {
sortedEnvelops(newVal, oldVal) {
// Unselect vanished envelopes
const newIds = newVal.map((env) => env.databaseId)
this.selection = this.selection.filter((id) => newIds.includes(id))
Expand Down Expand Up @@ -381,7 +393,7 @@ export default {
let nextEnvelopeToNavigate
let isAllSelected
if (this.selectedEnvelopes.length === this.envelopes.length) {
if (this.selectedEnvelopes.length === this.sortedEnvelops.length) {
isAllSelected = true
} else {
const indexSelectedEnvelope = this.selectedEnvelopes.findIndex((selectedEnvelope) =>
Expand All @@ -390,7 +402,7 @@ export default {
// one of threads is selected
if (indexSelectedEnvelope !== -1) {
const lastSelectedEnvelope = this.selectedEnvelopes[this.selectedEnvelopes.length - 1]
const diff = this.envelopes.filter(envelope => envelope === lastSelectedEnvelope || !this.selectedEnvelopes.includes(envelope))
const diff = this.sortedEnvelops.filter(envelope => envelope === lastSelectedEnvelope || !this.selectedEnvelopes.includes(envelope))
const lastIndex = diff.indexOf(lastSelectedEnvelope)
nextEnvelopeToNavigate = diff[lastIndex === 0 ? 1 : lastIndex - 1]
}
Expand Down Expand Up @@ -460,12 +472,12 @@ export default {
const end = Math.max(this.lastToggledIndex, index)
const selected = this.selection.includes(envelope.databaseId)
for (let i = start; i <= end; i++) {
this.setEnvelopeSelected(this.envelopes[i], !selected)
this.setEnvelopeSelected(this.sortedEnvelops[i], !selected)
}
this.lastToggledIndex = index
},
unselectAll() {
this.envelopes.forEach((env) => {
this.sortedEnvelops.forEach((env) => {
env.flags.selected = false
})
this.selection = []
Expand Down
6 changes: 6 additions & 0 deletions src/components/Mailbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ export default {
}
},
computed: {
sortOrder() {
return this.$store.getters.getPreference('sort-order', 'DESC')
},
envelopes() {
return this.$store.getters.getEnvelopes(this.mailbox.databaseId, this.searchQuery)
},
Expand Down Expand Up @@ -176,6 +179,9 @@ export default {
searchQuery() {
this.loadEnvelopes()
},
sortOrder() {
this.loadEnvelopes()
},
},
created() {
this.bus.$on('load-more', this.onScroll)
Expand Down
Loading

0 comments on commit 625dd2b

Please sign in to comment.