diff --git a/init.lua b/init.lua index adeedb4..7fc6260 100644 --- a/init.lua +++ b/init.lua @@ -16,6 +16,7 @@ mail = { inbox = {}, outbox = {}, drafts = {}, + trash = {}, contacts = {}, maillists = {}, to = {}, @@ -32,7 +33,8 @@ mail = { hud_notifications = {}, sound_notifications = {}, unreadcolorenable = {}, - cccolorenable = {} + cccolorenable = {}, + trash_move_enable = {} }, message_drafts = {} @@ -58,6 +60,7 @@ dofile(MP .. "/ui/mail.lua") dofile(MP .. "/ui/inbox.lua") dofile(MP .. "/ui/outbox.lua") dofile(MP .. "/ui/drafts.lua") +dofile(MP .. "/ui/trash.lua") dofile(MP .. "/ui/message.lua") dofile(MP .. "/ui/events.lua") dofile(MP .. "/ui/contacts.lua") diff --git a/storage.lua b/storage.lua index 576064a..334cc8b 100644 --- a/storage.lua +++ b/storage.lua @@ -8,6 +8,7 @@ local function populate_entry(e) e.inbox = e.inbox or {} e.outbox = e.outbox or {} e.drafts = e.drafts or {} + e.trash = e.trash or {} e.lists = e.lists or {} e.settings = e.settings or {} return e @@ -42,6 +43,43 @@ function mail.get_message(playername, msg_id) return msg end end + for _, msg in ipairs(entry.drafts) do + if msg.id == msg_id then + return msg + end + end + for _, msg in ipairs(entry.trash) do + if msg.id == msg_id then + return msg + end + end +end + +-- get player boxes where a message appears +function mail.get_message_boxes(playername, msg_id) + local entry = mail.get_storage_entry(playername) + local boxes = {} + for _, msg in ipairs(entry.inbox) do + if msg.id == msg_id then + table.insert(boxes, "inbox") + end + end + for _, msg in ipairs(entry.outbox) do + if msg.id == msg_id then + table.insert(boxes, "outbox") + end + end + for _, msg in ipairs(entry.drafts) do + if msg.id == msg_id then + table.insert(boxes, "drafts") + end + end + for _, msg in ipairs(entry.trash) do + if msg.id == msg_id then + table.insert(boxes, "trash") + end + end + return boxes end local function safe_find(str, sub) @@ -109,7 +147,7 @@ function mail.mark_unread(playername, msg_ids) end -- deletes a mail by its id -function mail.delete_mail(playername, msg_ids) +function mail.delete_mail(playername, msg_ids, delete_in_trash) local entry = mail.get_storage_entry(playername) if type(msg_ids) ~= "table" then -- if this is not a table msg_ids = { msg_ids } @@ -135,8 +173,53 @@ function mail.delete_mail(playername, msg_ids) end end end + if delete_in_trash then + for i = #entry.trash, 1, -1 do + for _, deleted_msg in ipairs(msg_ids) do + if entry.trash[i].id == deleted_msg then + table.remove(entry.trash, i) + end + end + end + end + mail.set_storage_entry(playername, entry) + mail.hud_update(playername, entry.inbox) + return +end + +-- move to trash mails by id +function mail.trash_mail(playername, msg_ids) + local entry = mail.get_storage_entry(playername) + if type(msg_ids) ~= "table" then -- if this is not a table + msg_ids = { msg_ids } + end + for _, id in ipairs(msg_ids) do + local msg = mail.get_message(playername, id) + msg.previous_boxes = mail.get_message_boxes(playername, id) + table.insert(entry.trash, 1, msg) + end + mail.set_storage_entry(playername, entry) + mail.delete_mail(playername, msg_ids) + return +end + +-- restore a mail from trash +function mail.restore_mail(playername, msg_id) + local entry = mail.get_storage_entry(playername) + for i, msg in ipairs(entry.trash) do + if msg.id == msg_id then + -- not anymore store previous boxes in json + local previous_boxes = msg.previous_boxes + msg.previous_boxes = nil + -- restore it in all previous boxes + for _, box in ipairs(previous_boxes) do + table.insert(entry[box], msg) + end + -- then delete it from trash + table.remove(entry.trash, i) + end + end mail.set_storage_entry(playername, entry) - mail.hud_update(playername, entry.inbox) return end @@ -268,6 +351,7 @@ function mail.get_setting_default_value(setting_name) cccolorenable = true, defaultsortfield = 3, defaultsortdirection = 1, + trash_move_enable = true, } return default_values[setting_name] end diff --git a/ui/drafts.lua b/ui/drafts.lua index 2d2cbd3..0a14c5a 100644 --- a/ui/drafts.lua +++ b/ui/drafts.lua @@ -2,7 +2,8 @@ local S = minetest.get_translator("mail") local drafts_formspec = "size[8.5,10;]" .. mail.theme .. [[ - tabheader[0.3,1;boxtab;]] .. S("Inbox") .. "," .. S("Outbox").. "," .. S("Drafts") .. [[;3;false;false] + tabheader[0.3,1;boxtab;]] .. + S("Inbox") .. "," .. S("Outbox").. "," .. S("Drafts") .. "," .. S("Trash") .. [[;3;false;false] button[6,0.10;2.5,0.5;new;]] .. S("New") .. [[] button[6,0.95;2.5,0.5;edit;]] .. S("Edit") .. [[] diff --git a/ui/events.lua b/ui/events.lua index dc25e98..9cb4055 100644 --- a/ui/events.lua +++ b/ui/events.lua @@ -15,7 +15,8 @@ local function nonempty(x) end minetest.register_on_player_receive_fields(function(player, formname, fields) - if formname ~= "mail:inbox" and formname ~= "mail:outbox" and formname ~= "mail:drafts" then + if formname ~= "mail:inbox" and formname ~= "mail:outbox" + and formname ~= "mail:drafts" and formname ~= "mail:trash" then return elseif fields.quit then return @@ -50,6 +51,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) -- split inbox and outbox msgs for different tests local entry = mail.get_storage_entry(name) local messagesDrafts = entry.drafts + local messagesTrash = entry.trash local getInbox = messageGetter(entry.inbox, inboxsortfield, sortdirection == "2", filter) local getOutbox = messageGetter(entry.outbox, outboxsortfield, sortdirection == "2", filter) @@ -154,6 +156,23 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) return true end + if fields.trash then -- trash table + local evt = minetest.explode_table_event(fields.trash) + if evt.row == 1 then -- header + if mail.selected_idxs.sortfield[name] == evt.column-1 then -- if already this field, then change direction + mail.selected_idxs.sortdirection[name] = mail.selected_idxs.sortdirection[name] == "2" and "1" or "2" + end + mail.selected_idxs.sortfield[name] = evt.column-1 -- update column + mail.show_mail_menu(name) + return + end + mail.selected_idxs.trash[name] = evt.row - 1 + if evt.type == "DCL" and messagesTrash[mail.selected_idxs.trash[name]] then + mail.show_message(name, messagesTrash[mail.selected_idxs.trash[name]].id) + end + return true + end + if fields.boxtab == "1" then mail.selected_idxs.boxtab[name] = 1 mail.show_inbox(name, sortfieldindex, sortdirection, filter) @@ -166,11 +185,17 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) mail.selected_idxs.boxtab[name] = 3 mail.show_drafts(name) + elseif fields.boxtab == "4" then + mail.selected_idxs.boxtab[name] = 4 + mail.show_trash(name) + elseif fields.read then if formname == "mail:inbox" and nonempty(mail.selected_idxs.inbox[name]) then -- inbox table mail.show_message(name, mail.selected_idxs.inbox[name][#mail.selected_idxs.inbox[name]]) elseif formname == "mail:outbox" and nonempty(mail.selected_idxs.outbox[name]) then -- outbox table mail.show_message(name, mail.selected_idxs.outbox[name][#mail.selected_idxs.outbox[name]]) + elseif formname == "mail:trash" and messagesTrash[mail.selected_idxs.trash[name]] then + mail.show_message(name, messagesTrash[mail.selected_idxs.trash[name]].id) end elseif fields.edit then @@ -186,19 +211,39 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end elseif fields.delete then + local trash_enabled = mail.get_setting(name, "trash_move_enable") if formname == "mail:inbox" and mail.selected_idxs.inbox[name] then -- inbox table - mail.delete_mail(name, mail.selected_idxs.inbox[name]) + if trash_enabled then + mail.trash_mail(name, mail.selected_idxs.inbox[name]) + else + mail.delete_mail(name, mail.selected_idxs.inbox[name]) + end mail.selected_idxs.inbox[name] = {} elseif formname == "mail:outbox" and mail.selected_idxs.outbox[name] then -- outbox table - mail.delete_mail(name, mail.selected_idxs.outbox[name]) + if trash_enabled then + mail.trash_mail(name, mail.selected_idxs.outbox[name]) + else + mail.delete_mail(name, mail.selected_idxs.outbox[name]) + end mail.selected_idxs.outbox[name] = {} 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) + if trash_enabled then + mail.trash_mail(name, messagesDrafts[mail.selected_idxs.drafts[name]].id) + else + mail.delete_mail(name, messagesDrafts[mail.selected_idxs.drafts[name]].id) + end mail.selected_idxs.drafts[name] = nil + + elseif formname == "mail:trash" and messagesTrash[mail.selected_idxs.trash[name]] then -- trash table + mail.delete_mail(name, messagesTrash[mail.selected_idxs.trash[name]].id, true) end mail.show_mail_menu(name, sortfieldindex, sortdirection, filter) + elseif fields.restore then + mail.restore_mail(name, messagesTrash[mail.selected_idxs.trash[name]].id) + mail.show_mail_menu(name, sortfieldindex, sortdirection, filter) + elseif fields.reply then if formname == "mail:inbox" and mail.selected_idxs.inbox[name] and #mail.selected_idxs.inbox[name] > 0 then local message = mail.get_message(name, mail.selected_idxs.inbox[name][#mail.selected_idxs.inbox[name]]) diff --git a/ui/inbox.lua b/ui/inbox.lua index 18490a3..e2c771b 100644 --- a/ui/inbox.lua +++ b/ui/inbox.lua @@ -14,7 +14,8 @@ function mail.show_inbox(name, sortfieldindex, sortdirection, filter) local messages = mail.sort_messages(entry.inbox, sortfield, sortdirection == "2", filter) local inbox_formspec = "size[8.5,10;]" .. mail.theme .. [[ - tabheader[0.3,1;boxtab;]] .. S("Inbox") .. "," .. S("Outbox").. "," .. S("Drafts") .. [[;1;false;false] + tabheader[0.3,1;boxtab;]] .. + S("Inbox") .. "," .. S("Outbox").. "," .. S("Drafts") .. "," .. S("Trash") .. [[;1;false;false] button[6,0.10;2.5,0.5;new;]] .. S("New") .. [[] button[6,0.95;2.5,0.5;read;]] .. S("Read") .. [[] diff --git a/ui/mail.lua b/ui/mail.lua index 6d1b9d4..9bf114f 100644 --- a/ui/mail.lua +++ b/ui/mail.lua @@ -11,5 +11,7 @@ function mail.show_mail_menu(playername, sortfield, sortdirection, filter) mail.show_outbox(playername, sortfield, sortdirection, filter) elseif index == 3 then mail.show_drafts(playername) + elseif index == 4 then + mail.show_trash(playername) end end diff --git a/ui/outbox.lua b/ui/outbox.lua index bce18b6..e55039b 100644 --- a/ui/outbox.lua +++ b/ui/outbox.lua @@ -14,7 +14,8 @@ function mail.show_outbox(name, sortfieldindex, sortdirection, filter) local messages = mail.sort_messages(entry.outbox, sortfield, sortdirection == "2", filter) local outbox_formspec = "size[8.5,10;]" .. mail.theme .. [[ - tabheader[0.3,1;boxtab;]] .. S("Inbox") .. "," .. S("Outbox").. "," .. S("Drafts") .. [[;2;false;false] + tabheader[0.3,1;boxtab;]] .. + S("Inbox") .. "," .. S("Outbox").. "," .. S("Drafts") .. "," .. S("Trash") .. [[;2;false;false] button[6,0.10;2.5,0.5;new;]] .. S("New") .. [[] button[6,0.95;2.5,0.5;read;]] .. S("Read") .. [[] diff --git a/ui/settings.lua b/ui/settings.lua index 0bca7a6..878febd 100644 --- a/ui/settings.lua +++ b/ui/settings.lua @@ -35,6 +35,11 @@ function mail.show_settings(name) S("Ascending") .. "," .. S("Descending") .. [[;]] .. tostring(mail.get_setting(name, "defaultsortdirection")) .. [[;true] + box[0,3.2;3,0.45;#466432] + label[0.2,3.2;]] .. S("Other") .. [[] + checkbox[0,3.6;trash_move_enable;]] .. S("Move deleted messages to trash") .. [[;]] .. + tostring(mail.get_setting(name, "trash_move_enable")) .. [[] + button[0,5.5;2.5,0.5;save;]] .. S("Save") .. [[] button[2.7,5.5;2.5,0.5;reset;]] .. S("Reset") .. [[] ]] .. mail.theme @@ -79,6 +84,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) elseif fields.cccolorenable then mail.selected_idxs.cccolorenable[playername] = fields.cccolorenable == "true" + elseif fields.trash_move_enable then + mail.selected_idxs.trash_move_enable[playername] = fields.trash_move_enable == "true" + elseif fields.save then -- checkboxes mail.set_setting(playername, "chat_notifications", mail.selected_idxs.chat_notifications[playername]) @@ -87,6 +95,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) mail.set_setting(playername, "sound_notifications", mail.selected_idxs.sound_notifications[playername]) mail.set_setting(playername, "unreadcolorenable", mail.selected_idxs.unreadcolorenable[playername]) mail.set_setting(playername, "cccolorenable", mail.selected_idxs.cccolorenable[playername]) + mail.set_setting(playername, "trash_move_enable", mail.selected_idxs.trash_move_enable[playername]) -- dropdowns local defaultsortfield = fields.defaultsortfield or mail.get_setting("defaultsortfield") local defaultsortdirection = fields.defaultsortdirection or mail.get_setting("defaultsortdirection") diff --git a/ui/trash.lua b/ui/trash.lua new file mode 100644 index 0000000..892a29a --- /dev/null +++ b/ui/trash.lua @@ -0,0 +1,52 @@ +-- translation +local S = minetest.get_translator("mail") + +local trash_formspec = "size[8.5,10;]" .. mail.theme .. [[ + tabheader[0.3,1;boxtab;]] .. + S("Inbox") .. "," .. S("Outbox").. "," .. S("Drafts") .. "," .. S("Trash") .. [[;4;false;false] + + button[6,0.10;2.5,0.5;new;]] .. S("New") .. [[] + button[6,0.95;2.5,0.5;read;]] .. S("Read") .. [[] + button[6,1.70;2.5,0.5;restore;]] .. S("Restore") .. [[] + button[6,2.45;2.5,0.5;delete;]] .. S("Delete") .. [[] + button[6,6.8;2.5,0.5;contacts;]] .. S("Contacts") .. [[] + button[6,7.6;2.5,0.5;maillists;]] .. S("Mail lists") .. [[] + button[6,8.7;2.5,0.5;options;]] .. S("Options") .. [[] + button_exit[6,9.5;2.5,0.5;quit;]] .. S("Close") .. [[] + + tablecolumns[color;text;text] + table[0,0.7;5.75,9.35;trash;#999,]] .. S("From/To") .. "," .. S("Subject") + + +function mail.show_trash(name) + local formspec = { trash_formspec } + local entry = mail.get_storage_entry(name) + local messages = entry.trash + + if messages[1] then + for _, message in ipairs(messages) do + formspec[#formspec + 1] = "," + formspec[#formspec + 1] = "," + formspec[#formspec + 1] = minetest.formspec_escape(message.to) + formspec[#formspec + 1] = "," + if message.subject ~= "" then + if string.len(message.subject) > 30 then + formspec[#formspec + 1] = minetest.formspec_escape(string.sub(message.subject, 1, 27)) + formspec[#formspec + 1] = "..." + else + formspec[#formspec + 1] = minetest.formspec_escape(message.subject) + end + else + formspec[#formspec + 1] = S("(No subject)") + end + end + if mail.selected_idxs.trash[name] then + formspec[#formspec + 1] = ";" + formspec[#formspec + 1] = tostring(mail.selected_idxs.trash[name] + 1) + end + formspec[#formspec + 1] = "]" + else + formspec[#formspec + 1] = "]label[2.25,4.5;" .. S("Trash is empty") .. "]" + end + minetest.show_formspec(name, "mail:trash", table.concat(formspec, "")) +end