ENH - add Mail selection and batch deletion

This commit is contained in:
DerEchteAlec
2026-08-13 03:10:45 +02:00
parent a98b3b0c98
commit cd28c64073
9 changed files with 838 additions and 289 deletions
+45 -2
View File
@@ -1389,7 +1389,9 @@ const accountDevices = [
const messages = [
{
body: '## Welcome to iFruit Mail\n\nYour shared mailbox is **ready to use**.\n\n- Send formatted messages\n- Keep drafts on every linked device\n- Reply without losing the conversation\n\n> Tip: use the small formatting bar while composing.',
created_at: '2026-08-04 11:30:00',
// Database dates may cross the NUI boundary as Unix timestamps.
// Keep one received message numeric so the browser preview covers that contract.
created_at: Date.parse('2026-08-04T11:30:00'),
folder: 'inbox',
id: 1,
is_read: false,
@@ -7064,7 +7066,13 @@ app.post('/api/:endpoint', (request, response) => {
return
}
if (endpoint === 'housing:overview') {
response.json({ success: true, data: mockHousingOverview })
response.json({
success: true,
data:
testScenario === 'house-empty'
? { ...mockHousingOverview, properties: [] }
: mockHousingOverview,
})
return
}
if (endpoint === 'housing:key-candidates') {
@@ -9003,6 +9011,41 @@ app.post('/api/:endpoint', (request, response) => {
response.json({ success: true, data: { id: 'mock-sent-message' } })
return
}
if (endpoint === 'mail:delete-many') {
const { folder, ids } = request.body
if (
!['drafts', 'inbox', 'sent', 'trash'].includes(folder) ||
!Array.isArray(ids)
) {
response.json({ success: false, error: 'invalid_request' })
return
}
const selectedIds = new Set(ids.map(String))
if (folder === 'drafts') {
if (draft && selectedIds.has(String(draft.id))) draft = null
} else if (folder === 'trash') {
for (let index = messages.length - 1; index >= 0; index -= 1) {
const message = messages[index]
if (message.trashed_at && selectedIds.has(String(message.id))) {
messages.splice(index, 1)
}
}
} else {
for (const message of messages) {
if (
message.folder === folder &&
!message.trashed_at &&
selectedIds.has(String(message.id))
) {
message.trashed_at = '2026-08-04 12:00:00'
}
}
}
response.json({ success: true })
return
}
if (endpoint === 'mail:trash' || endpoint === 'mail:restore') {
const message = messages.find((item) => item.id === Number(request.body.id))
if (message)
+67 -1
View File
@@ -297,7 +297,73 @@ async function verifyStatefulActions(baseUrl) {
true,
)
assert.equal(storedDraft.subject, 'Browser test mail')
await expectSuccess(baseUrl, 'mail:delete-draft', { id: draft.id })
await expectSuccess(baseUrl, 'mail:delete-many', {
folder: 'drafts',
ids: [draft.id],
})
const drafts = await expectSuccess(
baseUrl,
'mail:list',
{ folder: 'drafts' },
true,
)
assert.equal(drafts.items.length, 0, 'mail:delete-many kept selected draft')
await expectSuccess(baseUrl, 'mail:delete-many', {
folder: 'inbox',
ids: [1],
})
const inbox = await expectSuccess(
baseUrl,
'mail:list',
{ folder: 'inbox' },
true,
)
assert(
inbox.items.some((message) => message.id === 2),
'mail:delete-many removed a non-selected inbox message',
)
const trash = await expectSuccess(
baseUrl,
'mail:list',
{ folder: 'trash' },
true,
)
assert(
trash.items.some((message) => message.id === 1),
'mail:delete-many did not move selected inbox mail to trash',
)
await expectSuccess(baseUrl, 'mail:delete-many', {
folder: 'sent',
ids: [3],
})
const sent = await expectSuccess(
baseUrl,
'mail:list',
{ folder: 'sent' },
true,
)
assert.equal(sent.items.length, 0, 'mail:delete-many kept selected sent mail')
await expectSuccess(baseUrl, 'mail:delete-many', {
folder: 'trash',
ids: [1],
})
const remainingTrash = await expectSuccess(
baseUrl,
'mail:list',
{ folder: 'trash' },
true,
)
assert(
!remainingTrash.items.some((message) => message.id === 1),
'mail:delete-many kept permanently deleted trash mail',
)
assert(
remainingTrash.items.some((message) => message.id === 4),
'mail:delete-many removed non-selected trash mail',
)
}
async function main() {