From 2b1a344d3d30689a3699fe9263dae90f0a3f7558 Mon Sep 17 00:00:00 2001 From: SX <50966843+S-S-X@users.noreply.github.com> Date: Sat, 8 Apr 2023 17:47:06 +0300 Subject: [PATCH] Rework mail.sort_messages --- storage.lua | 35 +++++++------- ui/events.lua | 124 +++++++++++++++++++++++++------------------------- ui/inbox.lua | 19 ++++---- ui/outbox.lua | 21 +++++---- 4 files changed, 103 insertions(+), 96 deletions(-) diff --git a/storage.lua b/storage.lua index 1fe6e8c..ac53b99 100644 --- a/storage.lua +++ b/storage.lua @@ -43,23 +43,26 @@ function mail.get_message(playername, msg_id) end end -function mail.sort_messages(messages, sortfield, sortdirection) - local function sorter(field, dir) - return dir == "2" - and (function(a, b) return a[field] > b[field] end) - or (function(a, b) return a[field] < b[field] end) +function mail.sort_messages(messages, sortfield, descending) + local results = {unpack(messages)} + if sortfield ~= nil then + if descending then + table.sort(results, function(a, b) + if a[sortfield] and b[sortfield] then + return a[sortfield] > b[sortfield] + end + minetest.log("warning", "mail.sort_messages: missing field "..sortfield) + end) + else + table.sort(results, function(a, b) + if a[sortfield] and b[sortfield] then + return a[sortfield] < b[sortfield] + end + minetest.log("warning", "mail.sort_messages: missing field "..sortfield) + end) + end end - local result = {unpack(messages)} - if sortfield == "1" then -- for inbox - table.sort(result, sorter("from", sortdirection)) - elseif sortfield == "1" then -- for outbox - table.sort(result, sorter("to", sortdirection)) - elseif sortfield == "2" then - table.sort(result, sorter("subject", sortdirection)) - else -- default sorting, sortfield == "3" - table.sort(result, sorter("time", sortdirection)) - end - return result + return results end function mail.filter_messages(unfiltered_messages, filter) diff --git a/ui/events.lua b/ui/events.lua index 85a7b14..487b666 100644 --- a/ui/events.lua +++ b/ui/events.lua @@ -1,42 +1,44 @@ + +-- Getter to filter and sort messages on demand +local function messageGetter(messages, sortfield, ascending, filter) + local results + return function() + if not results then + results = mail.sort_messages(mail.filter_messages(messages, filter), sortfield, ascending) + end + return results + end +end + minetest.register_on_player_receive_fields(function(player, formname, fields) if formname ~= "mail:inbox" and formname ~= "mail:sent" and formname ~= "mail:drafts" then return end + -- Get player name and handle / convert common input fields local name = player:get_player_name() + local filter = fields.filter or "" + local sortfieldindex = tonumber(fields.sortfield or mail.selected_idxs.sortfield[name]) or 3 + local sortdirection = fields.sortdirection or mail.selected_idxs.sortdirection[name] or "1" + local inboxsortfield = ({"from","subject","time"})[sortfieldindex] + local outboxsortfield = ({"to","subject","time"})[sortfieldindex] + + -- Store common player configuration for reuse + mail.selected_idxs.sortfield[name] = sortfieldindex + mail.selected_idxs.sortdirection[name] = sortdirection -- split inbox and sent msgs for different tests local entry = mail.get_storage_entry(name) - - local messagesInboxUnAnalyzed = entry.inbox - local messagesOutBoxUnAnalyzed = entry.outbox local messagesDrafts = entry.drafts + local getInbox = messageGetter(entry.inbox, inboxsortfield, sortdirection == "2", filter) + local getOutbox = messageGetter(entry.outbox, outboxsortfield, sortdirection == "2", filter) - -- filter inbox/outbox messages - - local filter = fields.filter - if not filter then - filter = "" - end - - local messagesInboxFiltered = mail.filter_messages(messagesInboxUnAnalyzed, filter) - local messagesOutboxFiltered = mail.filter_messages(messagesOutBoxUnAnalyzed, filter) - - -- then sort them - - local sortfield = fields.sortfield or mail.selected_idxs.sortfield[name] or "3" - local sortdirection = fields.sortdirection or mail.selected_idxs.sortdirection[name] or "1" - mail.selected_idxs.sortfield[name] = sortfield - mail.selected_idxs.sortdirection[name] = sortdirection - - local messagesInbox = mail.sort_messages(messagesInboxFiltered, sortfield, sortdirection, filter) - local messagesSent = mail.sort_messages(messagesOutboxFiltered, sortfield, sortdirection, filter) - + -- Hanmdle formspec event if fields.inbox then -- inbox table local evt = minetest.explode_table_event(fields.inbox) mail.selected_idxs.inbox[name] = evt.row - 1 - if evt.type == "DCL" and messagesInbox[mail.selected_idxs.inbox[name]] then - mail.show_message(name, messagesInbox[mail.selected_idxs.inbox[name]].id) + if evt.type == "DCL" and getInbox()[mail.selected_idxs.inbox[name]] then + mail.show_message(name, getInbox()[mail.selected_idxs.inbox[name]].id) end return true end @@ -44,8 +46,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.sent then -- sent table local evt = minetest.explode_table_event(fields.sent) mail.selected_idxs.sent[name] = evt.row - 1 - if evt.type == "DCL" and messagesSent[mail.selected_idxs.sent[name]] then - mail.show_message(name, messagesSent[mail.selected_idxs.sent[name]].id) + if evt.type == "DCL" and getOutbox()[mail.selected_idxs.sent[name]] then + mail.show_message(name, getOutbox()[mail.selected_idxs.sent[name]].id) end return true end @@ -68,21 +70,21 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.boxtab == "1" then mail.selected_idxs.boxtab[name] = 1 - mail.show_inbox(name, sortfield, sortdirection, filter) + mail.show_inbox(name, sortfieldindex, sortdirection, filter) elseif fields.boxtab == "2" then mail.selected_idxs.boxtab[name] = 2 - mail.show_sent(name, sortfield, sortdirection, filter) + mail.show_sent(name, sortfieldindex, sortdirection, filter) elseif fields.boxtab == "3" then mail.selected_idxs.boxtab[name] = 3 mail.show_drafts(name) elseif fields.read then - if formname == "mail:inbox" and messagesInbox[mail.selected_idxs.inbox[name]] then -- inbox table - mail.show_message(name, messagesInbox[mail.selected_idxs.inbox[name]].id) - elseif formname == "mail:sent" and messagesSent[mail.selected_idxs.sent[name]] then -- sent table - mail.show_message(name, messagesSent[mail.selected_idxs.sent[name]].id) + if formname == "mail:inbox" and getInbox()[mail.selected_idxs.inbox[name]] then -- inbox table + mail.show_message(name, getInbox()[mail.selected_idxs.inbox[name]].id) + elseif formname == "mail:sent" and getOutbox()[mail.selected_idxs.sent[name]] then -- sent table + mail.show_message(name, getOutbox()[mail.selected_idxs.sent[name]].id) end elseif fields.edit then @@ -98,60 +100,60 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end elseif fields.delete then - if formname == "mail:inbox" and messagesInbox[mail.selected_idxs.inbox[name]] then -- inbox table - mail.delete_mail(name, messagesInbox[mail.selected_idxs.inbox[name]].id) - elseif formname == "mail:sent" and messagesSent[mail.selected_idxs.sent[name]] then -- sent table - mail.delete_mail(name, messagesSent[mail.selected_idxs.sent[name]].id) + if formname == "mail:inbox" and getInbox()[mail.selected_idxs.inbox[name]] then -- inbox table + mail.delete_mail(name, getInbox()[mail.selected_idxs.inbox[name]].id) + elseif formname == "mail:sent" and getOutbox()[mail.selected_idxs.sent[name]] then -- sent table + mail.delete_mail(name, getOutbox()[mail.selected_idxs.sent[name]].id) elseif formname == "mail:drafts" and messagesDrafts[mail.selected_idxs.drafts[name]] then -- drafts table mail.delete_mail(name, messagesDrafts[mail.selected_idxs.drafts[name]].id) end - mail.show_mail_menu(name, sortfield, sortdirection, filter) + mail.show_mail_menu(name, sortfieldindex, sortdirection, filter) elseif fields.reply then - if formname == "mail:inbox" and messagesInbox[mail.selected_idxs.inbox[name]] then - local message = messagesInbox[mail.selected_idxs.inbox[name]] + if formname == "mail:inbox" and getInbox()[mail.selected_idxs.inbox[name]] then + local message = getInbox()[mail.selected_idxs.inbox[name]] mail.reply(name, message) - elseif formname == "mail:sent" and messagesSent[mail.selected_idxs.sent[name]] then - local message = messagesSent[mail.selected_idxs.sent[name]] + elseif formname == "mail:sent" and getOutbox()[mail.selected_idxs.sent[name]] then + local message = getOutbox()[mail.selected_idxs.sent[name]] mail.reply(name, message) end elseif fields.replyall then - if formname == "mail:inbox" and messagesInbox[mail.selected_idxs.inbox[name]] then - local message = messagesInbox[mail.selected_idxs.inbox[name]] + if formname == "mail:inbox" and getInbox()[mail.selected_idxs.inbox[name]] then + local message = getInbox()[mail.selected_idxs.inbox[name]] mail.replyall(name, message) - elseif formname == "mail:sent" and messagesSent[mail.selected_idxs.sent[name]] then - local message = messagesSent[mail.selected_idxs.sent[name]] + elseif formname == "mail:sent" and getOutbox()[mail.selected_idxs.sent[name]] then + local message = getOutbox()[mail.selected_idxs.sent[name]] mail.replyall(name, message) end elseif fields.forward then - if formname == "mail:inbox" and messagesInbox[mail.selected_idxs.inbox[name]] then - local message = messagesInbox[mail.selected_idxs.inbox[name]] + if formname == "mail:inbox" and getInbox()[mail.selected_idxs.inbox[name]] then + local message = getInbox()[mail.selected_idxs.inbox[name]] mail.forward(name, message) - elseif formname == "mail:sent" and messagesSent[mail.selected_idxs.sent[name]] then - local message = messagesSent[mail.selected_idxs.sent[name]] + elseif formname == "mail:sent" and getOutbox()[mail.selected_idxs.sent[name]] then + local message = getOutbox()[mail.selected_idxs.sent[name]] mail.forward(name, message) end elseif fields.markread then - if formname == "mail:inbox" and messagesInbox[mail.selected_idxs.inbox[name]] then - mail.mark_read(name, messagesInbox[mail.selected_idxs.inbox[name]].id) - elseif formname == "mail:sent" and messagesSent[mail.selected_idxs.sent[name]] then - mail.mark_read(name, messagesSent[mail.selected_idxs.sent[name]].id) + if formname == "mail:inbox" and getInbox()[mail.selected_idxs.inbox[name]] then + mail.mark_read(name, getInbox()[mail.selected_idxs.inbox[name]].id) + elseif formname == "mail:sent" and getOutbox()[mail.selected_idxs.sent[name]] then + mail.mark_read(name, getOutbox()[mail.selected_idxs.sent[name]].id) end - mail.show_mail_menu(name, sortfield, sortdirection, filter) + mail.show_mail_menu(name, sortfieldindex, sortdirection, filter) elseif fields.markunread then - if formname == "mail:inbox" and messagesInbox[mail.selected_idxs.inbox[name]] then - mail.mark_unread(name, messagesInbox[mail.selected_idxs.inbox[name]].id) - elseif formname == "mail:sent" and messagesSent[mail.selected_idxs.sent[name]] then - mail.mark_unread(name, messagesSent[mail.selected_idxs.sent[name]].id) + if formname == "mail:inbox" and getInbox()[mail.selected_idxs.inbox[name]] then + mail.mark_unread(name, getInbox()[mail.selected_idxs.inbox[name]].id) + elseif formname == "mail:sent" and getOutbox()[mail.selected_idxs.sent[name]] then + mail.mark_unread(name, getOutbox()[mail.selected_idxs.sent[name]].id) end - mail.show_mail_menu(name, sortfield, sortdirection, filter) + mail.show_mail_menu(name, sortfieldindex, sortdirection, filter) elseif fields.new then mail.show_compose(name) @@ -166,7 +168,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) mail.show_about(name) elseif fields.sortfield or fields.sortdirection or fields.filter then - mail.show_mail_menu(name, sortfield, sortdirection, filter) + mail.show_mail_menu(name, sortfieldindex, sortdirection, filter) end return true diff --git a/ui/inbox.lua b/ui/inbox.lua index 2ea6c60..a538abd 100644 --- a/ui/inbox.lua +++ b/ui/inbox.lua @@ -2,13 +2,10 @@ local S = minetest.get_translator("mail") -function mail.show_inbox(name, sortfield, sortdirection, filter) - sortfield = sortfield or mail.selected_idxs.sortfield[name] or "3" +function mail.show_inbox(name, sortfieldindex, sortdirection, filter) + sortfieldindex = tonumber(sortfieldindex or mail.selected_idxs.sortfield[name]) or 3 sortdirection = sortdirection or mail.selected_idxs.sortdirection[name] or "1" - - if not filter then - filter = "" - end + filter = filter or "" local inbox_formspec = "size[8.5,10;]" .. mail.theme .. [[ tabheader[0.3,1;boxtab;]] .. S("Inbox") .. "," .. S("Sent messages").. "," .. S("Drafts") .. [[;1;false;false] @@ -27,7 +24,7 @@ function mail.show_inbox(name, sortfield, sortdirection, filter) button_exit[6,9.5;2.5,0.5;quit;]] .. S("Close") .. [[] dropdown[0,9.4;2,0.5;sortfield;]] .. - S("From") .. "," .. S("Subject") .. "," .. S("Date") .. [[;]] .. sortfield .. [[;true] + S("From") .. "," .. S("Subject") .. "," .. S("Date") .. [[;]] .. sortfieldindex .. [[;true] dropdown[2.0,9.4;2,0.5;sortdirection;]] .. S("Ascending") .. "," .. S("Descending") .. [[;]] .. sortdirection .. [[;true] field[4.25,9.85;1.4,0.5;filter;]] .. S("Filter") .. [[:;]] .. filter .. [[] @@ -37,11 +34,15 @@ function mail.show_inbox(name, sortfield, sortdirection, filter) table[0,0.7;5.75,8.35;inbox;#999,]] .. S("From") .. "," .. S("Subject") local formspec = { inbox_formspec } local entry = mail.get_storage_entry(name) - local messages = mail.sort_messages(mail.filter_messages(entry.inbox, filter), sortfield, sortdirection) + local messages = mail.sort_messages( + mail.filter_messages(entry.inbox, filter), + ({"from","subject","time"})[sortfieldindex], + sortdirection == "2" + ) mail.message_drafts[name] = nil - if messages[1] then + if #messages > 0 then for _, message in ipairs(messages) do if not message.read then if not mail.player_in_list(name, message.to) then diff --git a/ui/outbox.lua b/ui/outbox.lua index 9e787e9..9d9175e 100644 --- a/ui/outbox.lua +++ b/ui/outbox.lua @@ -2,13 +2,10 @@ local S = minetest.get_translator("mail") -function mail.show_sent(name, sortfield, sortdirection, filter) - sortfield = sortfield or mail.selected_idxs.sortfield[name] or "3" +function mail.show_sent(name, sortfieldindex, sortdirection, filter) + sortfieldindex = tonumber(sortfieldindex or mail.selected_idxs.sortfield[name]) or 3 sortdirection = sortdirection or mail.selected_idxs.sortdirection[name] or "1" - - if not filter then - filter = "" - end + filter = filter or "" local sent_formspec = "size[8.5,10;]" .. mail.theme .. [[ tabheader[0.3,1;boxtab;]] .. S("Inbox") .. "," .. S("Sent messages").. "," .. S("Drafts") .. [[;2;false;false] @@ -25,9 +22,9 @@ function mail.show_sent(name, sortfield, sortdirection, filter) button_exit[6,9.5;2.5,0.5;quit;]] .. S("Close") .. [[] dropdown[0,9.4;2,0.5;sortfield;]] - .. S("To") .. "," .. S("Subject") .. "," .. S("Date") .. [[;]] .. tostring(sortfield) .. [[;1] + .. S("To") .. "," .. S("Subject") .. "," .. S("Date") .. [[;]] .. sortfieldindex .. [[;1] dropdown[2.0,9.4;2,0.5;sortdirection;]] - .. S("Ascending") .. "," .. S("Descending") .. [[;]] .. tostring(sortdirection) .. [[;1] + .. S("Ascending") .. "," .. S("Descending") .. [[;]] .. sortdirection .. [[;1] field[4.25,9.85;1.4,0.5;filter;]].. S("Filter") .. [[:;]] .. filter .. [[] button[5.14,9.52;0.85,0.5;search;Q] @@ -35,11 +32,15 @@ function mail.show_sent(name, sortfield, sortdirection, filter) table[0,0.7;5.75,8.35;sent;#999,]] .. S("To") .. "," .. S("Subject") local formspec = { sent_formspec } local entry = mail.get_storage_entry(name) - local messages = mail.sort_messages(mail.filter_messages(entry.outbox, filter), sortfield, sortdirection) + local messages = mail.sort_messages( + mail.filter_messages(entry.outbox, filter), + ({"to","subject","time"})[sortfieldindex], + sortdirection == "2" + ) mail.message_drafts[name] = nil - if messages[1] then + if #messages > 0 then for _, message in ipairs(messages) do formspec[#formspec + 1] = "," formspec[#formspec + 1] = ","