diff --git a/ui/about.lua b/ui/about.lua new file mode 100644 index 0000000..cd50405 --- /dev/null +++ b/ui/about.lua @@ -0,0 +1,152 @@ +-- translation +local S = mail.S + +local FORMNAME = "mail:about" + +local groups = { + { "o", S("Original author")}, + { "c", S("Code")}, + { "i", S("Internationalization")}, + { "t", S("Textures")}, + { "a", S("Audio")}, +} + +local contributors = { + { name = "Cheapie", groups = {"o", "c"} }, + { name = "aBlueShadow", groups = {"c"} }, + { name = "APercy", groups = {"i"} }, + { name = "Athozus", groups = {"c", "i"} }, + { name = "BuckarooBanzay", groups = {"c"} }, + { name = "Chache", groups = {"i"} }, + { name = "Dennis Jenkins", groups = {"c"} }, + { name = "Emojigit", groups = {"c", "i"} }, + { name = "Eredin", groups = {"i"} }, + { name = "fluxionary", groups = {"c"} }, + { name = "imre84", groups = {"c"} }, + { name = "Muhammad Rifqi Priyo Susanto", groups = {"i"} }, + { name = "NatureFreshMilk", groups = {"c", "t"} }, + { name = "Niklp", groups = {"c", "i"} }, + { name = "Nuno Filipe Povoa", groups = {"a"} }, + { name = "nyomi", groups = {"i"} }, + { name = "OgelGames", groups = {"c"} }, + { name = "Panquesito7", groups = {"c"} }, + { name = "Peter Nerlich", groups = {"c"} }, + { name = "Rubenwardy", groups = {"c"} }, + { name = "savilli", groups = {"c"} }, + { name = "Singularis", groups = {"c"} }, + { name = "SX", groups = {"c"} }, + { name = "TheTrueBeginner", groups = {"i"} }, + { name = "Thomas Rudin", groups = {"c"} }, + { name = "Toby1710", groups = {"c"} }, + { name = "whosit", groups = {"c"} }, + { name = "Wuzzy", groups = {"i"} }, + { name = "y5nw", groups = {"c", "i"} }, +} + +function mail.show_about(name) + mail.selected_idxs.contributor_grouping[name] = tonumber(mail.selected_idxs.contributor_grouping[name]) or 1 + + local formspec = [[ + size[10,6;] + tabheader[0,0;optionstab;]] .. S("Settings") .. "," .. S("About") .. [[;2;false;false] + button[9.35,0;0.75,0.5;back;X] + + box[0,0;3,0.45;]] .. mail.get_color("highlighted") .. [[] + label[0.2,0;Mail] + + label[0.2,0.5;]] .. S("Provided by mt-mods") .. [[] + label[0.2,0.9;]] .. S("Version: @1", "1.5.0-dev") .. [[] + + box[0,1.5;3,0.45;]] .. mail.get_color("highlighted") .. [[] + label[0.2,1.5;]] .. S("Licenses") .. [[] + label[0.2,2.0;]] .. S("Expat (code), WTFPL (textures)") .. [[] + + box[0,2.6;3,0.45;]] .. mail.get_color("highlighted") .. [[] + label[0.2,2.6;]] .. S("Note") .. [[] + textarea[0.5,3.15;4,5.5;;;]] .. + S("Communication using this system is NOT guaranteed to be private!") .. " " .. + S("Admins are able to view the messages of any player.") .. [[] + + button[0,5.7;2,0.5;github;GitHub] + button[2,5.7;2,0.5;contentdb;ContentDB] + + box[4,0;3,0.45;]] .. mail.get_color("highlighted") .. [[] + label[4.2,0;]] .. S("Contributors") .. [[] + + dropdown[4,0.75;6.4;contributor_grouping;]] + .. S("Group by name") .. "," + .. S("Group by contribution") .. ";" .. mail.selected_idxs.contributor_grouping[name] .. [[;true] + ]] + + local contributor_list, contributor_columns = {} + + if mail.selected_idxs.contributor_grouping[name] == 2 then + contributor_columns = "color;text" + local sorted = {} + for _, g in ipairs(groups) do + sorted[g[1]] = {} + end + for _, c in ipairs(contributors) do + for _, g in ipairs(c.groups) do + table.insert(sorted[g] or {}, c.name) + end + end + for _, g in ipairs(groups) do + table.insert(contributor_list, mail.get_color("header") .. "," .. g[2]) + for _, c in ipairs(sorted[g[1]]) do + table.insert(contributor_list, "," .. c) + end + end + else + contributor_columns = "text;text" + for _, c in ipairs(contributors) do + for _, g in ipairs(groups) do + local index = table.indexof(c.groups, g[1]) + if index >= 1 then + if index == 1 then + table.insert(contributor_list, c.name) + else + table.insert(contributor_list, "") + end + table.insert(contributor_list, g[2]) + end + end + end + end + + formspec = formspec .. ("tablecolumns[%s]"):format(contributor_columns) .. + ("table[4,1.6;5.9,4.65;contributors;%s]"):format(table.concat(contributor_list, ",")) + + formspec = formspec .. mail.theme + + minetest.show_formspec(name, FORMNAME, formspec) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= FORMNAME then + return + end + + local playername = player:get_player_name() + + if fields.back then + mail.show_mail_menu(playername) + + elseif fields.optionstab == "1" then + mail.selected_idxs.optionstab[playername] = 1 + mail.show_settings(playername) + + elseif fields.optionstab == "2" then + mail.selected_idxs.optionstab[playername] = 2 + mail.show_about(playername) + + elseif fields.github then + minetest.chat_send_player(playername, "https://github.com/mt-mods/mail") + + elseif fields.contentdb then + minetest.chat_send_player(playername, "https://content.minetest.net/packages/mt-mods/mail") + elseif fields.contributor_grouping then + mail.selected_idxs.contributor_grouping[playername] = fields.contributor_grouping + mail.show_about(playername) + end +end) diff --git a/ui/compose.lua b/ui/compose.lua new file mode 100644 index 0000000..62d16a2 --- /dev/null +++ b/ui/compose.lua @@ -0,0 +1,129 @@ +-- translation +local S = mail.S + +local FORMNAME = "mail:compose" + +function mail.show_compose(name, to, subject, body, cc, bcc, id) + local formspec = [[ + size[8,9] + button[0,0;1,1;tocontacts;]] .. S("To") .. [[:] + field[1.1,0.3;3.2,1;to;;%s] + button[4,0;1,1;cccontacts;]] .. S("CC") .. [[:] + field[5.1,0.3;3.1,1;cc;;%s] + button[4,0.75;1,1;bcccontacts;]] .. S("BCC") .. [[:] + field[5.1,1.05;3.1,1;bcc;;%s] + field[0.25,2;8,1;subject;]] .. S("Subject") .. [[:;%s] + textarea[0.25,2.5;8,6;body;;%s] + button[0.1,8.5;2.5,1;cancel;]] .. S("Cancel") .. [[] + button[2.7,8.5;2.5,1;draft;]] .. S("Save draft") .. [[] + button[5.3,8.5;2.5,1;send;]] .. S("Send") .. [[] + ]] .. mail.theme + + formspec = string.format(formspec, + minetest.formspec_escape(to) or "", + minetest.formspec_escape(cc) or "", + minetest.formspec_escape(bcc) or "", + minetest.formspec_escape(subject) or "", + minetest.formspec_escape(body) or "") + + mail.selected_idxs.message[name] = id or mail.new_uuid() + + minetest.show_formspec(name, FORMNAME, formspec) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= FORMNAME then + return + end + + local name = player:get_player_name() + if fields.send then + local id = mail.selected_idxs.message[name] or mail.new_uuid() + if (fields.to == "" and fields.cc == "" and fields.bcc == "") or fields.body == "" then + -- if mail is invalid then store it as a draft + mail.save_draft({ + id = id, + from = name, + to = fields.to, + cc = fields.cc, + bcc = fields.bcc, + subject = fields.subject, + body = fields.body + }) + mail.show_mail_menu(name) + return + end + local success, err = mail.send({ + id = id, + from = name, + to = fields.to, + cc = fields.cc, + bcc = fields.bcc, + subject = fields.subject, + body = fields.body, + }) + if not success then + minetest.chat_send_player(name, err) + return + end + + -- add new contacts if some receivers aren't registered + local contacts = mail.get_contacts(name) + local recipients = mail.parse_player_list(fields.to) + local isNew = true + for _,recipient in ipairs(recipients) do + if recipient:sub(1,1) == "@" then -- in case of maillist -- check if first char is @ + isNew = false + else + for _,contact in ipairs(contacts) do + if contact.name == recipient then + isNew = false + break + end + end + end + if isNew then + mail.update_contact(name, {name = recipient, note = ""}) + end + end + + minetest.after(0.5, function() + mail.selected_idxs.drafts[name] = nil + mail.show_mail_menu(name) + end) + + elseif fields.tocontacts or fields.cccontacts or fields.bcccontacts then + mail.message_drafts[name] = { + to = fields.to, + cc = fields.cc, + bcc = fields.bcc, + subject = fields.subject, + body = fields.body, + } + mail.show_select_contact(name, fields.to, fields.cc, fields.bcc) + + elseif fields.cancel then + mail.message_drafts[name] = nil + + mail.show_mail_menu(name) + + elseif fields.draft then + local id = mail.new_uuid() + if mail.selected_idxs.message[name] then + id = mail.selected_idxs.message[name] + end + mail.save_draft({ + id = id, + from = name, + to = fields.to, + cc = fields.cc, + bcc = fields.bcc, + subject = fields.subject, + body = fields.body + }) + + mail.show_mail_menu(name) + end + + return true +end) diff --git a/ui/contacts.lua b/ui/contacts.lua new file mode 100644 index 0000000..3978251 --- /dev/null +++ b/ui/contacts.lua @@ -0,0 +1,86 @@ +-- translation +local S = mail.S + +local FORMNAME = "mail:contacts" + +local contacts_formspec = "size[8,9;]" .. mail.theme .. [[ + button[6,0.10;2,0.5;new;]] .. S("New") .. [[] + button[6,0.85;2,0.5;edit;]] .. S("Edit") .. [[] + button[6,1.60;2,0.5;delete;]] .. S("Delete") .. [[] + button[6,8.25;2,0.5;back;]] .. S("Back") .. [[] + tablecolumns[color;text;text] + table[0,0;5.75,9;contacts;]] .. mail.get_color("header") .. "," .. S("Name") .. "," .. S("Note") + + +function mail.show_contacts(name) + local formspec = contacts_formspec .. mail.compile_contact_list(name, mail.selected_idxs.contacts[name]) + minetest.show_formspec(name, FORMNAME, formspec) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= FORMNAME then + return + end + + local name = player:get_player_name() + local contacts = mail.get_contacts(name) + + if fields.contacts then + local evt = minetest.explode_table_event(fields.contacts) + for k, _, i in mail.pairs_by_keys(contacts) do + if i == evt.row - 1 then + mail.selected_idxs.contacts[name] = tonumber(k) + break + end + end + if evt.type == "DCL" and contacts[mail.selected_idxs.contacts[name]] then + mail.show_edit_contact( + name, + contacts[mail.selected_idxs.contacts[name]].name, + contacts[mail.selected_idxs.contacts[name]].note + ) + end + + elseif fields.new then + mail.selected_idxs.contacts[name] = "#NEW#" + mail.show_edit_contact(name, "", "") + + elseif fields.edit and mail.selected_idxs.contacts[name] and contacts[mail.selected_idxs.contacts[name]] then + mail.show_edit_contact( + name, + contacts[mail.selected_idxs.contacts[name]].name, + contacts[mail.selected_idxs.contacts[name]].note + ) + + elseif fields.delete then + if contacts[mail.selected_idxs.contacts[name]] then + -- delete the contact and set the selected to the next in the list, + -- except if it was the last. Then determine the new last + local found = false + local last = nil + for k in mail.pairs_by_keys(contacts) do + if found then + mail.selected_idxs.contacts[name] = tonumber(k) + break + elseif k == mail.selected_idxs.contacts[name] then + mail.delete_contact(name, contacts[mail.selected_idxs.contacts[name]].name) + mail.selected_idxs.contacts[name] = nil + found = true + else + last = tonumber(k) + end + end + if found and not mail.selected_idxs.contacts[name] then + -- was the last in the list, so take the previous (new last) + mail.selected_idxs.contacts[name] = last + end + end + + mail.show_contacts(name) + + elseif fields.back then + mail.show_mail_menu(name) + end + + return true +end) diff --git a/ui/drafts.lua b/ui/drafts.lua new file mode 100644 index 0000000..003e3cc --- /dev/null +++ b/ui/drafts.lua @@ -0,0 +1,57 @@ +-- translation +local S = mail.S + +function mail.show_drafts(name) + local trash_tab = "" + if mail.get_setting(name, "trash_move_enable") then + trash_tab = "," .. S("Trash") + end + + local drafts_formspec = "size[8.5,11;]" .. mail.theme .. [[ + tabheader[0.3,1;boxtab;]] .. + S("Inbox") .. "," .. S("Outbox").. "," .. S("Drafts") .. trash_tab .. [[;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") .. [[] + button[6,1.70;2.5,0.5;delete;]] .. S("Delete") .. [[] + button[6,8.0;2.5,0.5;contacts;]] .. S("Contacts") .. [[] + button[6,8.8;2.5,0.5;maillists;]] .. S("Mail lists") .. [[] + button[6,9.7;2.5,0.5;options;]] .. S("Options") .. [[] + button_exit[6,10.5;2.5,0.5;quit;]] .. S("Close") .. [[] + + tablecolumns[color;text;text] + table[0,0.7;5.75,10.35;drafts;]] .. mail.get_color("header") .. "," .. S("To") .. "," .. S("Subject") + + local formspec = { drafts_formspec } + local entry = mail.get_storage_entry(name) + local messages = entry.drafts + + mail.message_drafts[name] = nil + + 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.drafts[name] then + formspec[#formspec + 1] = ";" + formspec[#formspec + 1] = tostring(mail.selected_idxs.drafts[name] + 1) + end + formspec[#formspec + 1] = "]" + else + formspec[#formspec + 1] = "]label[2.25,4.5;" .. S("No drafts") .. "]" + end + minetest.show_formspec(name, "mail:drafts", table.concat(formspec, "")) +end diff --git a/ui/edit_contact.lua b/ui/edit_contact.lua new file mode 100644 index 0000000..c8e00e3 --- /dev/null +++ b/ui/edit_contact.lua @@ -0,0 +1,77 @@ +-- translation +local S = mail.S + +local FORMNAME = "mail:editcontact" + +function mail.show_edit_contact(name, contact_name, note, illegal_name_hint) + local formspec = [[ + size[6,7] + button[4,6.25;2,0.5;back;]] .. S("Back") .. [[] + field[0.25,0.5;4,1;name;]] .. S("Player name") .. [[:;%s] + textarea[0.25,1.6;4,6.25;note;]] .. S("Note") .. [[:;%s] + button[4,0.10;2,1;save;]] .. S("Save") .. [[] + ]] + if illegal_name_hint == "collision" then + formspec = formspec .. [[ + textarea[4.25,1;2.5,6;;;]] .. + S("That name is already in your contacts") .. [[] + ]] + elseif illegal_name_hint == "empty" then + formspec = formspec .. [[ + textarea[4.25,1;2.5,6;;;]] .. + S("The contact name cannot be empty.") .. [[] + ]] + end + formspec = formspec .. mail.theme + formspec = string.format(formspec, + minetest.formspec_escape(contact_name or ""), + minetest.formspec_escape(note or "")) + minetest.show_formspec(name, FORMNAME, formspec) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= FORMNAME then + return + end + + local name = player:get_player_name() + local contacts = mail.get_contacts(name) + + if fields.save then + if mail.selected_idxs.contacts[name] then + local contact = contacts[mail.selected_idxs.contacts[name]] or {name = ""} + if contact.name ~= fields.name or fields.name == "" then + -- name changed! + if #fields.name == 0 then + mail.show_edit_contact(name, contact.name, fields.note, "empty") + return true + + elseif mail.get_contact(name, fields.name) then + mail.show_edit_contact(name, contact.name, fields.note, "collision") + return true + + else + contact.name = fields.name + contact.note = fields.note + mail.update_contact(name, contact) + contacts[mail.selected_idxs.contacts[name]] = nil + end + end + contact.name = fields.name + contact.note = fields.note + mail.update_contact(name, contact) + + else + mail.update_contact(name, { + name = fields.name, + note = fields.note, + }) + end + mail.show_contacts(name) + + elseif fields.back then + mail.show_contacts(name) + end + + return true +end)