Skip to content

Commit 54e9aeb

Browse files
authored
Merge pull request #11264 from nextcloud/feat/add-byDate-sections
feat: split envelopes by time of arrival
2 parents c563201 + eaa7405 commit 54e9aeb

File tree

5 files changed

+113
-9
lines changed

5 files changed

+113
-9
lines changed

src/components/EnvelopeList.vue

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -574,9 +574,6 @@ div {
574574
#load-more-mail-messages {
575575
margin: 10px auto;
576576
padding: 10px;
577-
margin-top: 50px;
578-
margin-bottom: 50px;
579-
padding-inline-start: 32px;
580577
background-position: 9px center;
581578
}
582579

src/components/Mailbox.vue

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@
1515
:slow-hint="t('mail', 'Indexing your messages. This can take a bit longer for larger folders.')" />
1616
<EmptyMailboxSection v-else-if="isPriorityInbox && !hasMessages" key="empty" />
1717
<EmptyMailbox v-else-if="!hasMessages" key="empty" />
18+
<template v-else-if="hasGroupedEnvelopes && !isPriorityInbox">
19+
<div v-for="[label, group] in Object.entries(groupEnvelopes)" :key="label">
20+
<SectionTitle class="section-title" :name="getLabelForGroup(label)" />
21+
<EnvelopeList :account="account"
22+
:mailbox="mailbox"
23+
:search-query="searchQuery"
24+
:envelopes="group"
25+
:loading-more="false"
26+
:load-more-button="false"
27+
:skip-transition="skipListTransition"
28+
@delete="onDelete" />
29+
</div>
30+
</template>
1831
<EnvelopeList v-else
1932
:account="account"
2033
:mailbox="mailbox"
@@ -30,6 +43,7 @@
3043

3144
<script>
3245
import EmptyMailbox from './EmptyMailbox.vue'
46+
import SectionTitle from './SectionTitle.vue'
3347
import EnvelopeList from './EnvelopeList.vue'
3448
import LoadingSkeleton from './LoadingSkeleton.vue'
3549
import Error from './Error.vue'
@@ -58,9 +72,15 @@ export default {
5872
Error,
5973
Loading,
6074
LoadingSkeleton,
75+
SectionTitle,
6176
},
6277
mixins: [isMobile],
6378
props: {
79+
groupEnvelopes: {
80+
type: Object,
81+
required: false,
82+
default: null,
83+
},
6484
account: {
6585
type: Object,
6686
required: true,
@@ -120,8 +140,14 @@ export default {
120140
}
121141
return this.envelopes
122142
},
143+
hasGroupedEnvelopes() {
144+
return this.groupEnvelopes && Object.keys(this.groupEnvelopes).length > 0
145+
},
123146
hasMessages() {
124-
return this.envelopes.length > 0
147+
if (this.hasGroupedEnvelopes) {
148+
return Object.values(this.groupEnvelopes).some(group => group.length > 0)
149+
}
150+
return this.envelopesToShow?.length > 0
125151
},
126152
showLoadMore() {
127153
return !this.endReached && this.paginate === 'manual'
@@ -466,6 +492,8 @@ export default {
466492
} finally {
467493
this.refreshing = false
468494
logger.debug(`finished sync'ing folder ${this.mailbox.databaseId} (${this.searchQuery})`, { init })
495+
496+
this.mainStore.updateSyncTimestamp()
469497
}
470498
},
471499
// onDelete(id): Load more message and navigate to other message if needed
@@ -528,6 +556,21 @@ export default {
528556
clearInterval(this.loadMailboxInterval)
529557
this.loadMailboxInterval = undefined
530558
},
559+
getLabelForGroup(group) {
560+
switch (group) {
561+
case 'lastHour':
562+
return t('mail', 'Last hour')
563+
case 'today':
564+
return t('mail', 'Today')
565+
case 'yesterday':
566+
return t('mail', 'Yesterday')
567+
case 'lastWeek':
568+
return t('mail', 'Last week')
569+
case 'lastMonth':
570+
return t('mail', 'Last month')
571+
}
572+
return t('mail', 'Older')
573+
},
531574
},
532575
}
533576
</script>

src/components/MailboxThread.vue

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@
3131
:mailbox="mailbox"
3232
:search-query="query"
3333
:bus="bus"
34-
:open-first="mailbox.specialRole !== 'drafts'" />
34+
:open-first="mailbox.specialRole !== 'drafts'"
35+
:group-envelopes="groupEnvelopes"
36+
:initial-page-size="messagesOrderBydate"
37+
:collapsible="true" />
3538
<template v-else>
3639
<div v-show="hasFollowUpEnvelopes"
3740
class="app-content-list-item">
@@ -191,6 +194,7 @@ export default {
191194
},
192195
computed: {
193196
...mapStores(useMainStore),
197+
194198
layoutMode() {
195199
return this.mainStore.getPreference('layout-mode', 'vertical-split')
196200
},
@@ -232,7 +236,12 @@ export default {
232236
return this.mainStore.getEnvelopes(this.mailbox.databaseId, this.searchQuery).length > 0
233237
},
234238
hasImportantEnvelopes() {
235-
return this.mainStore.getEnvelopes(this.unifiedInbox.databaseId, this.appendToSearch(priorityImportantQuery)).length > 0
239+
const map = this.mainStore.getEnvelopes(
240+
this.unifiedInbox.databaseId,
241+
this.appendToSearch(this.priorityImportantQuery),
242+
)
243+
const envelopes = Array.isArray(map) ? map : Array.from(map?.values() || [])
244+
return envelopes.length > 0
236245
},
237246
/**
238247
* @return {boolean}
@@ -242,9 +251,9 @@ export default {
242251
return false
243252
}
244253
245-
return this.mainStore
246-
.getEnvelopes(FOLLOW_UP_MAILBOX_ID, this.followUpQuery)
247-
.length > 0
254+
const map = this.mainStore.getEnvelopes(FOLLOW_UP_MAILBOX_ID, this.followUpQuery)
255+
const envelopes = Array.isArray(map) ? map : Array.from(map?.values() || [])
256+
return envelopes.length > 0
248257
},
249258
importantMessagesInitialPageSize() {
250259
if (window.innerHeight > 1024) {
@@ -255,6 +264,12 @@ export default {
255264
}
256265
return 3
257266
},
267+
/**
268+
* @return {number}
269+
*/
270+
messagesOrderBydate() {
271+
return 10
272+
},
258273
/**
259274
* @return {number}
260275
*/
@@ -277,6 +292,10 @@ export default {
277292
isThreadShown() {
278293
return !!this.$route.params.threadId
279294
},
295+
groupEnvelopes() {
296+
const allEnvelopes = this.mainStore.getEnvelopes(this.mailbox.databaseId, this.searchQuery)
297+
return this.groupEnvelopesByDate(allEnvelopes, this.mainStore.syncTimestamp)
298+
},
280299
},
281300
watch: {
282301
async $route(to) {
@@ -313,6 +332,47 @@ export default {
313332
clearTimeout(this.startMailboxTimer)
314333
},
315334
methods: {
335+
groupEnvelopesByDate(envelopes, syncTimestamp) {
336+
const now = new Date(syncTimestamp)
337+
const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000)
338+
const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate())
339+
const startOfYesterday = new Date(startOfToday)
340+
startOfYesterday.setDate(startOfYesterday.getDate() - 1)
341+
const startOfLastWeek = new Date(now)
342+
startOfLastWeek.setDate(startOfLastWeek.getDate() - 7)
343+
const startOfLastMonth = new Date(now)
344+
startOfLastMonth.setMonth(startOfLastMonth.getMonth() - 1)
345+
346+
const groups = {
347+
lastHour: [],
348+
today: [],
349+
yesterday: [],
350+
lastWeek: [],
351+
lastMonth: [],
352+
older: [],
353+
}
354+
355+
for (const envelope of envelopes) {
356+
const date = new Date(envelope.dateInt * 1000)
357+
if (date >= oneHourAgo) {
358+
groups.lastHour.push(envelope)
359+
} else if (date >= startOfToday) {
360+
groups.today.push(envelope)
361+
} else if (date >= startOfYesterday && date < startOfToday) {
362+
groups.yesterday.push(envelope)
363+
} else if (date >= startOfLastWeek) {
364+
groups.lastWeek.push(envelope)
365+
} else if (date >= startOfLastMonth) {
366+
groups.lastMonth.push(envelope)
367+
} else {
368+
groups.older.push(envelope)
369+
}
370+
}
371+
372+
return Object.fromEntries(
373+
Object.entries(groups).filter(([_, list]) => list.length > 0),
374+
)
375+
},
316376
async fetchEnvelopes() {
317377
const existingEnvelopes = this.mainStore.getEnvelopes(this.mailbox.databaseId, this.searchQuery || '')
318378
if (!existingEnvelopes.length) {

src/store/mainStore.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
export default defineStore('main', {
1717
state: () => {
1818
return {
19+
syncTimestamp: Date.now(),
1920
isExpiredSession: false,
2021
preferences: {},
2122
accountsUnmapped: {

src/store/mainStore/actions.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ function transformMailboxName(account, mailbox) {
189189

190190
export default function mainStoreActions() {
191191
return {
192+
updateSyncTimestamp() {
193+
this.syncTimestamp = Date.now()
194+
},
192195
savePreference({
193196
key,
194197
value,

0 commit comments

Comments
 (0)