From 1c049fc07171ca3c576fdaf7b0429562f2cdb872 Mon Sep 17 00:00:00 2001 From: moparisthebest Date: Thu, 11 Aug 2016 12:52:04 -0400 Subject: [PATCH] Send deletes across websocket and handle in poll as well so deletes update in realtime --- assets/javascripts/mailcatcher.js.coffee | 50 +++++++++++++++++------- lib/mail_catcher/mail.rb | 45 +++++++++++++-------- 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/assets/javascripts/mailcatcher.js.coffee b/assets/javascripts/mailcatcher.js.coffee index 44112c5..ed66216 100644 --- a/assets/javascripts/mailcatcher.js.coffee +++ b/assets/javascripts/mailcatcher.js.coffee @@ -103,14 +103,8 @@ class MailCatcher url: "/messages/" + id type: "DELETE" success: => - messageRow = $("""#messages tbody tr[data-message-id="#{id}"]""") - switchTo = messageRow.next().data("message-id") || messageRow.prev().data("message-id") - messageRow.remove() - if switchTo - @loadMessage switchTo - else - @unselectMessage() - @updateMessagesCount() + # callback will delete, this gets us into race conditions... + #@deleteMessage [id] error: -> alert "Error while removing message." @@ -171,9 +165,8 @@ class MailCatcher else @nextTab(i + 1) - haveMessage: (message) -> - message = message.id if message.id? - $("""#messages tbody tr[data-message-id="#{message}"]""").length > 0 + haveMessage: (id) -> + $("""#messages tbody tr[data-message-id="#{id}"]""").length > 0 selectedMessage: -> $("#messages tr.selected").data "message-id" @@ -198,6 +191,21 @@ class MailCatcher row.prependTo($("#messages tbody")) @updateMessagesCount() + deleteMessage: (ids) -> + selectedId = @selectedMessage() + for id in ids + if @haveMessage id + messageRow = $("""#messages tbody tr[data-message-id="#{id}"]""") + if messageRow + if id == selectedId + switchTo = messageRow.next().data("message-id") || messageRow.prev().data("message-id") + messageRow.remove() + if switchTo && @haveMessage switchTo + @loadMessage switchTo + #else if selectedId + # @unselectMessage() + @updateMessagesCount() + scrollToRow: (row) -> relativePosition = row.offset().top - $("#messages").offset().top if relativePosition < 0 @@ -211,7 +219,7 @@ class MailCatcher $("#messages tbody, #message .metadata dd").empty() $("#message .metadata .attachments").hide() $("#message iframe").attr("src", "about:blank") - null + true loadMessage: (id) -> id = id.id if id?.id? @@ -283,10 +291,18 @@ class MailCatcher refresh: -> $.getJSON "/messages", (messages) => + all_msg_ids = [] $.each messages, (i, message) => - unless @haveMessage message + id = message.id if message.id? + all_msg_ids.push(id) + unless @haveMessage id @addMessage message - @updateMessagesCount() + ids_to_remove = [] + $.each $("#messages tbody tr[data-message-id]"), (i, row) => + existing_id = $(row).data("message-id") + unless existing_id in all_msg_ids + ids_to_remove.push(existing_id) + @deleteMessage ids_to_remove subscribe: -> if WebSocket? @@ -299,7 +315,11 @@ class MailCatcher protocol = if secure then "wss" else "ws" @websocket = new WebSocket("#{protocol}://#{window.location.host}/messages") @websocket.onmessage = (event) => - @addMessage $.parseJSON event.data + message = $.parseJSON event.data + if 'id' of message + @addMessage message + else + @deleteMessage message subscribePoll: -> unless @refreshInterval? diff --git a/lib/mail_catcher/mail.rb b/lib/mail_catcher/mail.rb index e044392..221f05b 100644 --- a/lib/mail_catcher/mail.rb +++ b/lib/mail_catcher/mail.rb @@ -158,32 +158,43 @@ module MailCatcher::Mail extend self end end - def delete! - @delete_all_messages_query ||= db.prepare "DELETE FROM message" - @delete_all_message_parts_query ||= db.prepare "DELETE FROM message_part" + def delete_ids_query!(query, *bind_vars) + ids ||= [] + query.execute(bind_vars).map do |row| + ids << row[0] + end + delete_ids!(ids) + end - @delete_all_messages_query.execute and - @delete_all_message_parts_query.execute + def delete_ids!(ids) + unless ids.empty? + id_query = ids.join(',') + + db.execute("DELETE FROM message WHERE id IN (#{id_query})") + db.execute("DELETE FROM message_part WHERE id IN (#{id_query})") + + EventMachine.next_tick do + MailCatcher::Events::MessageAdded.push ids + end + end + end + + def delete! + @delete_all_messages_query ||= db.prepare "SELECT id FROM message" + delete_ids_query!(@delete_all_messages_query) end def delete_message!(message_id) - @delete_messages_query ||= db.prepare "DELETE FROM message WHERE id = ?" - @delete_message_parts_query ||= db.prepare "DELETE FROM message_part WHERE message_id = ?" - @delete_messages_query.execute(message_id) and - @delete_message_parts_query.execute(message_id) + delete_ids!([message_id.to_i]) end def delete_messages_older_than!(modifier) - @delete_messages_older_than_query ||= db.prepare "DELETE FROM message WHERE created_at < datetime('now', ?)" - @delete_message_parts_older_than_query ||= db.prepare "DELETE FROM message_part WHERE created_at < datetime('now', ?)" - @delete_messages_older_than_query.execute(modifier) and - @delete_message_parts_older_than_query.execute(modifier) + @delete_messages_older_than_query ||= db.prepare "SELECT id FROM message WHERE created_at < datetime('now', ?)" + delete_ids_query!(@delete_messages_older_than_query, modifier) end def delete_messages_keep!(keep_num_emails) - @delete_messages_query ||= db.prepare "DELETE FROM message WHERE id IN (SELECT id FROM message ORDER BY id DESC LIMIT -1 OFFSET ?);" - @delete_message_parts_query ||= db.prepare "DELETE FROM message_part WHERE id NOT IN (SELECT id FROM message)" - @delete_messages_query.execute(keep_num_emails) and - @delete_message_parts_query.execute() + @delete_messages_older_than_query ||= db.prepare "SELECT id FROM message ORDER BY id DESC LIMIT -1 OFFSET ?" + delete_ids_query!(@delete_messages_older_than_query, keep_num_emails) end end