Some considerations in the design so far:
Desired flows:
Should we autosave? I think not yet, because my editor's undo/redo functionality is not accessible yet on mobile. Android devices can't press 'ctrl', and the hotkeys aren't very discoverable.
(I considered menu options for 'undo' and 'redo', but they won't be very ergonomic because my undo/redo functionality is primitive and doesn't support grouping similar operations. Now you're stuck tapping '>>', then 'undo' and losing one character. Then the menu closes and you have to do it all over again.)
Another knock against autosave on mobile: autosave on quit is unreliable. At least on my Android devices, LÖVE doesn't trigger love.quit when you swipe away an app. iOS of course has no such notion in the first place.
Menu buttons take up space, and I'm loath to expend 2 more buttons. However, I don't see a good alternative:
We can't use a single button to bind a filename to a pane until we get autosave.
Save on run? It doesn't save a button, but maybe we can keep 'save' up top because we'll want to keep hitting it in the absence of autosave. However, I don't want to lose data just because I started typing out a long program that never got to a runnable point.
I'd like to keep 'save' always up. But newcomers might have more trouble finding things if load and save are separated from each other. Seems like the sort of thing Mike complained about before the current button organization.
==> conclusion: no autosave, 2 buttons, load and save
I want to follow MiniIDE and only save to a single directory (no subdirectories, even). Simplifies the file dialog.
Where should this directory live? Source base risks growing really large and unwieldy over time as we share files between lots of LÖVE apps. At least, Mike has that problem. Save dir is utterly inaccessible to other apps – including later versions of this one. Once you delete one version of an app (say before installing a new version) the only way to find your files is to wade through lots of cryptic directories inside source dir. And you'd need a new LÖVE app to do that.
==> conclusion: save to a fixed subdir of source base dir. That way only Lua Carousel will save there, but different versions share a common space.
==> conclusion: allow examples to be saved, but that creates a new copy of them on restart. It'll be weird that the order changes, but seems like the best option.
Still to do: providing a non-existing file to load/save. I plan a command palette UI for filtering or selecting a new file.
FIUQJVL2MCC4VKKX7JBT6377TWIGPTUC5NXMUABV5JILB3ZDWZFAC
5MEJ7XNHNFG2BIX3TFU6PDJHSJOS2Z45L25QAZKFGRW7ZNOFEUKAC
ZENSSO3DFZKXGQB54DQUS5Q6A6ADB7X7XCMCLX27Y5DGWQUZSIEAC
R5QXEHUIZLELJGGCZAE7ATNS3CLRJ7JFRENMGH4XXH24C5WABZDQC
RK2ASPN7A55RCEG2YRFZLFXNPSME2VKBE2ZXO257DYZPS5TPXC5QC
5RUFNRJOK3PXQKJTPDEN5K5PI67MGB25QUA44WOCCH2O5KHXT45QC
6RYGW5H3J44O73WFXGFVTBW5N5UEQ4E732AJJUZNBVQLYDA5LGLAC
VAVXKWZVOFJGWHCWYLTPDKSKKMSJEBKXNKXUW3T6IZAC3HE6HOIQC
ZM7NOBRMD5HHA35Y4JDC76EOA2RD4KQOQCPURXYKXA6ABMKOJIGQC
PRE6XPRNICDCHMF7C45A6DRPVT47IPAIWW6Q7AHNGW3D2PBGOPNAC
one_time_load = function()
print('loading '..Current_pane.filename)
Current_pane.editor_state.filename = Directory..Current_pane.filename
load_from_disk(Current_pane.editor_state)
Text.redraw_all(Current_pane.editor_state)
-- Disable autosave; undo isn't accessible in mobile devices.
Current_pane.editor_state.filename = nil
end
one_time_save = function()
print('saving to '..Current_pane.filename)
Current_pane.editor_state.filename = Directory..Current_pane.filename
save_to_disk(Current_pane.editor_state)
-- Don't autosave yet; undo isn't accessible in mobile devices.
Current_pane.editor_state.filename = nil
end
-- Function that is called when a 'filename' is selected from the file dialog, e.g. to load from or save to a file.
File_dialog_callback = nil
refresh_directory_contents = function()
Directory_contents = {}
local files_info = nativefs.getDirectoryItemsInfo(Directory)
for _,file_info in ipairs(files_info) do
if file_info.type == 'file' then
table.insert(Directory_contents, file_info.name)
end
end
table.sort(Directory_contents)
end
-- filenames inside directory
Directory_contents = nil
Directory = love.filesystem.getSourceBaseDirectory()..'/carousel_data/'
Show_file_dialog = false
draw_file_dialog = function()
App.color(Menu_background)
love.graphics.rectangle('fill',
Menu_left+5,
Menu_bottom+5,
Safe_width-Menu_left-10,
Safe_height-Menu_bottom-10)
if Directory_contents == nil then
-- on the first frame after dialog is enabled
refresh_directory_contents()
end
local x, y = Menu_left+10, Menu_bottom+10
for _,filename in ipairs(Directory_contents) do
local w = App.width(filename) + 10
if x == Menu_left+10 or x+w < Safe_width-Menu_left-10 then
styled_button(filename, x,y, function()
File_dialog_callback(filename)
Show_file_dialog = false
File_dialog_callback = nil
end)
x = x+w+10
else
x = Menu_left+10
y = y+Line_height+10
if y > Safe_height-Menu_bottom-10 then
break
end
end
end
end
load_button = function(x, y, r)
return overflowable_button('load', x, y, r,
function()
Directory_contents = nil -- refresh from file system
Show_file_dialog = true
File_dialog_callback = function(filename)
Current_pane.filename = filename
one_time_load()
end
end)
end
save_button = function(x, y, r)
return overflowable_button('save', x, y, r,
function()
print('save')
if Current_pane.filename == nil then
Directory_contents = nil -- refresh from file system
Show_file_dialog = true
File_dialog_callback = function(filename)
Current_pane.filename = filename
one_time_save()
end
else
one_time_save()
end
end)
end
-- Lua Carousel is almost entirely in a single (adjustable) font, but we make one exception to squeeze in a file name
Title_font = nil
love.graphics.line(x1,y1, x2,y1)
if Current_pane.filename then
-- title in between if it exists
local old_font = love.graphics.getFont()
if Title_font == nil then
Title_font = love.graphics.newFont(15) -- 20 pixels between menu and upper border - 5
end
love.graphics.setFont(Title_font)
local tx1 = Current_pane.editor_state.left
local tx2 = tx1 + App.width(Current_pane.filename)
love.graphics.print(Current_pane.filename, tx1, y1-15+5)
love.graphics.setFont(old_font)
love.graphics.line(x1,y1, tx1-5,y1)
love.graphics.line(math.min(tx2+5,x2), y1, x2,y1)
else
love.graphics.line(x1,y1, x2,y1)
end