always sort contacts alphabetically

- introduce pairsByKeys() (from http://www.lua.org/pil/19.3.html but adding current index and total length as iterator return values)
- use pairsByKeys() everywhere, where contacts are iterated over (for now only when displaying in gui.lua) so the order stays the same although the structure is a hashmap
- correctly update selected position when adding/removing contacts to TO/CC/BCC fields
- remove print statements in storage.lua
This commit is contained in:
Peter Nerlich 2020-08-15 13:52:26 +02:00
parent 39f47437b6
commit 93d1af947c
2 changed files with 51 additions and 21 deletions

51
gui.lua
View File

@ -181,9 +181,10 @@ function mail.compile_contact_list(name, selected, playernames)
local formspec = {}
local contacts = mail.getContacts(name)
local i = 0
if playernames == nil then
for k, contact in pairs(contacts) do
local length = 0
for k, contact, i, l in pairsByKeys(contacts) do
if i == 1 then length = l end
formspec[#formspec + 1] = ","
formspec[#formspec + 1] = ","
formspec[#formspec + 1] = minetest.formspec_escape(contact.name)
@ -195,15 +196,14 @@ function mail.compile_contact_list(name, selected, playernames)
note = string.sub(note, 1, idx-1) .. ' ...'
end
formspec[#formspec + 1] = minetest.formspec_escape(note)
i = i + 1
if type(selected) == "string" then
if selected == k then
if string.lower(selected) == k then
selected = i
end
end
end
if i > 0 then
if selected then
if length > 0 then
if selected and type(selected) == "number" then
formspec[#formspec + 1] = ";"
formspec[#formspec + 1] = tostring(selected + 1)
end
@ -215,7 +215,7 @@ function mail.compile_contact_list(name, selected, playernames)
if type(playernames) == "string" then
playernames = mail.parse_player_list(playernames)
end
for k,c in pairs(playernames) do
for i,c in ipairs(playernames) do
formspec[#formspec + 1] = ","
formspec[#formspec + 1] = ","
formspec[#formspec + 1] = minetest.formspec_escape(c)
@ -231,16 +231,15 @@ function mail.compile_contact_list(name, selected, playernames)
end
formspec[#formspec + 1] = minetest.formspec_escape(note)
end
i = i + 1
if not selected then
if type(selected) == "string" then
if k == selected then
if string.lower(selected) == string.lower(c) then
selected = i
end
end
end
end
if i > 0 and selected then
if #playernames > 0 and selected and type(selected) == "number" then
formspec[#formspec + 1] = ";"
formspec[#formspec + 1] = tostring(selected + 1)
end
@ -523,10 +522,8 @@ function mail.handle_receivefields(player, formname, fields)
if fields[v.."add"] then
update = true
if selected_idxs.contacts[name] then
local i = 0
for k, contact in pairs(contacts) do
i = i+1
if i == selected_idxs.contacts[name] then
for k, contact, i in pairsByKeys(contacts) do
if k == selected_idxs.contacts[name] or i == selected_idxs.contacts[name] then
local list = mail.parse_player_list(draft[v])
list[#list+1] = contact.name
selected_idxs[v][name] = #list
@ -573,10 +570,7 @@ function mail.handle_receivefields(player, formname, fields)
if fields.contacts then
local evt = minetest.explode_table_event(fields.contacts)
--selected_idxs.contacts[name] = evt.row - 1
local i = 0
for k,c in pairs(contacts) do
i = i + 1
for k,c,i in pairsByKeys(contacts) do
if i == evt.row - 1 then
selected_idxs.contacts[name] = k
break
@ -593,7 +587,26 @@ function mail.handle_receivefields(player, formname, fields)
mail.show_edit_contact(name, contacts[selected_idxs.contacts[name]].name, contacts[selected_idxs.contacts[name]].note)
elseif fields.delete then
if contacts[selected_idxs.contacts[name]] then
contacts[selected_idxs.contacts[name]] = nil
-- 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,v,i in pairsByKeys(contacts) do
if found then
selected_idxs.contacts[name] = k
break
elseif k == selected_idxs.contacts[name] then
contacts[selected_idxs.contacts[name]] = nil
selected_idxs.contacts[name] = nil
found = true
else
last = k
end
end
if found and not selected_idxs.contacts[name] then
-- was the last in the list, so take the previous (new last)
selected_idxs.contacts[name] = last
end
mail.setContacts(name, contacts)
end

View File

@ -36,6 +36,25 @@ mail.getContacts = function(playername)
return mail.read_json_file(mail.getContactsFile(playername))
end
function pairsByKeys(t, f)
-- http://www.lua.org/pil/19.3.html
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function() -- iterator function
i = i + 1
if a[i] == nil then
return nil
else
--return a[i], t[a[i]]
-- add the current position and the length for convenience
return a[i], t[a[i]], i, #a
end
end
return iter
end
mail.setContacts = function(playername, contacts)
if mail.write_json_file(mail.getContactsFile(playername), contacts) then
return true
@ -51,7 +70,6 @@ function mail.read_json_file(path)
local content = {}
if file then
local json = file:read("*a")
print(string.format('read from %s: %s', path, json))
content = minetest.parse_json(json or "[]") or {}
file:close()
end
@ -61,7 +79,6 @@ end
function mail.write_json_file(path, content)
local file = io.open(path,"w")
local json = minetest.write_json(content)
print(string.format('writing to %s: %s', path, json))
if file and file:write(json) and file:close() then
return true
else