Skip to content

Commit

Permalink
Merge branch 'release/v1.20.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
axllent committed Aug 10, 2024
2 parents 3fdbcaf + 8f1b804 commit 37ea30f
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 58 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

Notable changes to Mailpit will be documented in this file.

## [v1.20.1]

### Chore
- Shift inbox pagination to inbox component
- Live load up to 100 new messages in sidebar ([#336](https://github.com/axllent/mailpit/issues/336))
- Show icon attachment in new side navigation message listing ([#345](https://github.com/axllent/mailpit/issues/345))

### Fix
- Correctly decode X-Tags message headers (RFC 2047) ([#344](https://github.com/axllent/mailpit/issues/344))


## [v1.20.0]

### Feature
Expand Down
4 changes: 2 additions & 2 deletions internal/storage/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func Store(body *[]byte) (string, error) {
ReplyTo: addressToSlice(env, "Reply-To"),
}

messageID := strings.Trim(env.Root.Header.Get("Message-ID"), "<>")
messageID := strings.Trim(env.GetHeader("Message-ID"), "<>")
created := time.Now()

// use message date instead of created date
Expand Down Expand Up @@ -116,7 +116,7 @@ func Store(body *[]byte) (string, error) {
tags := findTagsInRawMessage(body)

if !config.TagsDisableXTags {
xTagsHdr := env.Root.Header.Get("X-Tags")
xTagsHdr := env.GetHeader("X-Tags")
if xTagsHdr != "" {
// extract tags from X-Tags header
tags = append(tags, tools.SetTagCasing(strings.Split(strings.TrimSpace(xTagsHdr), ","))...)
Expand Down
53 changes: 3 additions & 50 deletions server/ui-src/components/Notifications.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export default {
socketBreaks: 0, // to track sockets that continually connect & disconnect, reset every 15s
pauseNotifications: false, // prevent spamming
version: false,
paginationDelayed: false, // for delayed pagination URL changes
}
},
Expand Down Expand Up @@ -56,20 +55,7 @@ export default {
// new messages
if (response.Type == "new" && response.Data) {
if (!mailbox.searching) {
if (pagination.start < 1) {
// push results directly into first page
mailbox.messages.unshift(response.Data)
if (mailbox.messages.length > pagination.limit) {
mailbox.messages.pop()
}
} else {
// update pagination offset
pagination.start++
// prevent "Too many calls to Location or History APIs within a short time frame"
this.delayedPaginationUpdate()
}
}
this.eventBus.emit("new", response.Data)
for (let i in response.Data.Tags) {
if (mailbox.tags.findIndex(e => { return e.toLowerCase() === response.Data.Tags[i].toLowerCase() }) < 0) {
Expand Down Expand Up @@ -106,10 +92,10 @@ export default {
}
} else if (response.Type == "delete" && response.Data) {
// broadcast for components
this.eventBus.emit("delete", response.Data);
this.eventBus.emit("delete", response.Data)
} else if (response.Type == "update" && response.Data) {
// broadcast for components
this.eventBus.emit("update", response.Data);
this.eventBus.emit("update", response.Data)
} else if (response.Type == "truncate") {
// broadcast for components
this.eventBus.emit("truncate")
Expand Down Expand Up @@ -171,39 +157,6 @@ export default {
}, 15000)
},
// This will only update the pagination offset at a maximum of 2x per second
// when viewing the inbox on > page 1, while receiving an influx of new messages.
delayedPaginationUpdate() {
if (this.paginationDelayed) {
return
}
this.paginationDelayed = true
window.setTimeout(() => {
const path = this.$route.path
const p = {
...this.$route.query
}
if (pagination.start > 0) {
p.start = pagination.start.toString()
} else {
delete p.start
}
if (pagination.limit != pagination.defaultLimit) {
p.limit = pagination.limit.toString()
} else {
delete p.limit
}
mailbox.autoPaginating = false // prevent reload of messages when URL changes
const params = new URLSearchParams(p)
this.$router.replace(path + '?' + params.toString())
this.paginationDelayed = false
}, 500)
},
browserNotify(title, message) {
if (!("Notification" in window)) {
return
Expand Down
5 changes: 0 additions & 5 deletions server/ui-src/mixins/CommonMixins.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,6 @@ export default {
return 'bi-file-arrow-down-fill'
},

// wrapper to update one or more messages with
updateMessages(messages, updates) {

},

// Returns a hex color based on a string.
// Values are stored in an array for faster lookup / processing.
colorHash(s) {
Expand Down
52 changes: 52 additions & 0 deletions server/ui-src/views/MailboxView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default {
return {
mailbox,
delayedRefresh: false,
paginationDelayed: false, // for delayed pagination URL changes
}
},
Expand All @@ -46,13 +47,15 @@ export default {
this.loadMailbox()
// subscribe to events
this.eventBus.on("new", this.handleWSNew)
this.eventBus.on("update", this.handleWSUpdate)
this.eventBus.on("delete", this.handleWSDelete)
this.eventBus.on("truncate", this.handleWSTruncate)
},
unmounted() {
// unsubscribe from events
this.eventBus.off("new", this.handleWSNew)
this.eventBus.off("update", this.handleWSUpdate)
this.eventBus.off("delete", this.handleWSDelete)
this.eventBus.off("truncate", this.handleWSTruncate)
Expand All @@ -73,6 +76,55 @@ export default {
this.loadMessages()
},
// This will only update the pagination offset at a maximum of 2x per second
// when viewing the inbox on > page 1, while receiving an influx of new messages.
delayedPaginationUpdate() {
if (this.paginationDelayed) {
return
}
this.paginationDelayed = true
window.setTimeout(() => {
const path = this.$route.path
const p = {
...this.$route.query
}
if (pagination.start > 0) {
p.start = pagination.start.toString()
} else {
delete p.start
}
if (pagination.limit != pagination.defaultLimit) {
p.limit = pagination.limit.toString()
} else {
delete p.limit
}
mailbox.autoPaginating = false // prevent reload of messages when URL changes
const params = new URLSearchParams(p)
this.$router.replace(path + '?' + params.toString())
this.paginationDelayed = false
}, 500)
},
// handler for websocket new messages
handleWSNew(data) {
if (pagination.start < 1) {
// push results directly into first page
mailbox.messages.unshift(data)
if (mailbox.messages.length > pagination.limit) {
mailbox.messages.pop()
}
} else {
// update pagination offset
pagination.start++
// prevent "Too many calls to Location or History APIs within a short time frame"
this.delayedPaginationUpdate()
}
},
// handler for websocket message updates
handleWSUpdate(data) {
for (let x = 0; x < this.mailbox.messages.length; x++) {
Expand Down
25 changes: 24 additions & 1 deletion server/ui-src/views/MessageView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export default {
apiSideNavParams: URLSearchParams,
apiIsMore: true,
messagesList: [],
liveLoaded: 0, // the number new messages prepended tp messageList
scrollLoading: false,
canLoadMore: true,
}
Expand Down Expand Up @@ -62,13 +63,15 @@ export default {
this.refreshUI()
// subscribe to events
this.eventBus.on("new", this.handleWSNew)
this.eventBus.on("update", this.handleWSUpdate)
this.eventBus.on("delete", this.handleWSDelete)
this.eventBus.on("truncate", this.handleWSTruncate)
},
unmounted() {
// unsubscribe from events
this.eventBus.off("new", this.handleWSNew)
this.eventBus.off("update", this.handleWSUpdate)
this.eventBus.off("delete", this.handleWSDelete)
this.eventBus.off("truncate", this.handleWSTruncate)
Expand Down Expand Up @@ -212,6 +215,18 @@ export default {
}, 30000)
},
// handler for websocket new messages
handleWSNew(data) {
// do not add when searching or >= 100 new messages have been received
if (this.mailbox.searching || this.liveLoaded >= 100) {
return
}
this.liveLoaded++
this.messagesList.unshift(data)
this.scrollSidebarToCurrent()
},
// handler for websocket message updates
handleWSUpdate(data) {
for (let x = 0; x < this.messagesList.length; x++) {
Expand Down Expand Up @@ -419,6 +434,10 @@ export default {
}
},
reloadWindow() {
location.reload()
},
initReleaseModal() {
this.modal('ReleaseModal').show()
window.setTimeout(() => {
Expand Down Expand Up @@ -537,7 +556,7 @@ export default {
<span class="ms-1">
Return to
<template v-if="mailbox.searching">search</template>
<template v-else>mailbox</template>
<template v-else>inbox</template>
</span>
<span class="badge rounded-pill ms-1 float-end text-bg-secondary" title="Unread messages"
v-if="mailbox.unread && !errorMessage">
Expand All @@ -548,6 +567,9 @@ export default {

<div class="flex-grow-1 overflow-y-auto px-1 me-n1" id="MessageList" ref="MessageList"
@scroll="scrollHandler">
<button v-if="liveLoaded >= 100" class="w-100 alert alert-warning small" @click="reloadWindow()">
Reload to see newer messages
</button>
<template v-if="messagesList && messagesList.length">
<div class="list-group">
<RouterLink v-for="message in messagesList" :to="'/view/' + message.ID" :key="message.ID"
Expand All @@ -566,6 +588,7 @@ export default {
</div>
</div>
<div class="col-auto small">
<i class="bi bi-paperclip h6" v-if="message.Attachments"></i>
{{ getRelativeCreated(message) }}
</div>
<div v-if="message.Tags.length" class="col-12">
Expand Down

0 comments on commit 37ea30f

Please sign in to comment.