Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ export class AppComponent implements OnInit, AfterViewInit, CanvasTableSelectLis
this.messageActionsHandler.searchService = searchService;
this.messageActionsHandler.messageListService = messagelistservice;
this.messageActionsHandler.snackBar = snackBar;
this.messageActionsHandler.deleteMessageHandler = (messageIds: number[]) => this.deleteMessages(messageIds);

this.renderer.listen(window, 'keydown', (evt: KeyboardEvent) => {
if (this.singlemailviewer.messageId) {
Expand Down Expand Up @@ -809,23 +810,35 @@ export class AppComponent implements OnInit, AfterViewInit, CanvasTableSelectLis

// Delete selected messages in current canvastable view
// If looking at Trash, this will be "delete permanently"
public deleteMessages() {
const messageIds = this.canvastable.rows.selectedMessageIds();
public deleteMessages(messageIds = this.canvastable.rows.selectedMessageIds()) {
if (messageIds.length === 0) {
return;
}

const currentMessageId = this.singlemailviewer?.messageId;
const deletingOpenMessage = !!currentMessageId && messageIds.includes(currentMessageId);
const nextMessageId = deletingOpenMessage
? this.canvastable.rows.getMessageIdAfterRemoving(messageIds, currentMessageId)
: null;

this.messageActionsHandler.updateMessages({
messageIds: messageIds,
updateLocal: (msgIds: number[]) => {
// remove from message display
this.canvastable.rows.removeMessages(messageIds);
this.canvastable.rows.removeMessages(msgIds);
this.searchService.deleteMessages(msgIds);
if (this.selectedFolder === this.messagelistservice.trashFolderName) {
this.messagelistservice.deleteTrashMessages(msgIds);
} else {
this.messagelistservice.moveMessages(msgIds, this.messagelistservice.trashFolderName);
}
this.clearSelection();
if (this.singlemailviewer && this.singlemailviewer.messageId && msgIds.includes(this.singlemailviewer.messageId)) {
this.singlemailviewer.close();
if (deletingOpenMessage) {
if (this.keepMessagePaneOpen && nextMessageId) {
this.selectRowByMessageId(nextMessageId);
} else if (this.singlemailviewer) {
this.singlemailviewer.close();
}
}
},
updateRemote: (msgIds: number[]) => this.rmmapi.deleteMessages(msgIds)
Expand Down
26 changes: 26 additions & 0 deletions src/app/canvastable/canvastable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,30 @@ describe('canvastable', () => {
expect(fixture.componentInstance.canvastable.floatingTooltip).toBeTruthy();
expect(fixture.componentInstance.canvastable.columnOverlay).toBeTruthy();
});

describe('message delete navigation', () => {
it('returns the next visible message after the opened message is removed', () => {
const rows = new MessageList([{ id: 10 }, { id: 20 }, { id: 30 }]);

expect(rows.getMessageIdAfterRemoving([20], 20)).toBe(30);
});

it('skips other removed messages when finding the next message', () => {
const rows = new MessageList([{ id: 10 }, { id: 20 }, { id: 30 }, { id: 40 }]);

expect(rows.getMessageIdAfterRemoving([20, 30], 20)).toBe(40);
});

it('falls back to the previous visible message at the end of the list', () => {
const rows = new MessageList([{ id: 10 }, { id: 20 }, { id: 30 }]);

expect(rows.getMessageIdAfterRemoving([30], 30)).toBe(20);
});

it('returns null when no visible messages remain', () => {
const rows = new MessageList([{ id: 10 }, { id: 20 }]);

expect(rows.getMessageIdAfterRemoving([10, 20], 10)).toBeNull();
});
});
});
28 changes: 28 additions & 0 deletions src/app/common/messagedisplay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,34 @@ export abstract class MessageDisplay {
});
}

public getMessageIdAfterRemoving(messageIds: number[], currentMessageId: number): number {
if (!currentMessageId) {
return null;
}

const currentRowIndex = this.findRowByMessageId(currentMessageId);
if (currentRowIndex < 0) {
return null;
}

const removedMessageIds = new Set(messageIds);
for (let index = currentRowIndex + 1; index < this.rowCount(); index++) {
const messageId = this.getRowMessageId(index);
if (!removedMessageIds.has(messageId)) {
return messageId;
}
}

for (let index = currentRowIndex - 1; index >= 0; index--) {
const messageId = this.getRowMessageId(index);
if (!removedMessageIds.has(messageId)) {
return messageId;
}
}

return null;
}

public removeMessages(messageIds: number[]) {
const filteredRows = [];
this.rows.forEach((value, index) => {
Expand Down
6 changes: 6 additions & 0 deletions src/app/mailviewer/rmm7messageactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export class RMM7MessageActions implements MessageActions {
messageListService: MessageListService;
draftDeskService: DraftDeskService;
rmmapi: RunboxWebmailAPI;
deleteMessageHandler?: (messageIds: number[]) => void;

public updateMessages(args: { messageIds: number[],
updateLocal: (messageIds: number[]) => void,
Expand Down Expand Up @@ -94,6 +95,11 @@ export class RMM7MessageActions implements MessageActions {
}

public deleteMessage() {
if (this.deleteMessageHandler) {
this.deleteMessageHandler([this.mailViewerComponent.messageId]);
return;
}

this.updateMessages({
messageIds: [this.mailViewerComponent.messageId],
updateLocal: (msgIds: number[]) => {
Expand Down