When I lost my iPad, I also lost all of my projects. Is there a way to backup projects onto another device or in the cloud?
@glwhart - there are a number of ways to back up. Using an external filing app or internally running the Codea backup facility from the main Codea system window. Also @dave1707 has written a number of project and project library backup projects. You can save each file as a zip file from the system backup options. Just check it out before you program further. You obviously need a storage option such as Dropbox to store them in.
If you lost your iPad, there’s not much you can do. If the iPad is brocken, you could still try to get it’s memory back.
@Bri_G I have dropbox and google drive so I could backup to one of those. Being somewhat new to Codea, I’m not sure how to do what you suggest. Could you offer step by step instructions for one of your proposed solutions? For example, I don’t know what you mean by “the main Codea system window”.
The easiest way is to hold on a project, three options will pop out. Select Copy Project Code and post it on pastebin/github, and on the other iPad run the installer.
local linkRawCode = "INSERT LINK TO WHERE YOUR CODE IS"
local function success(data)
if data:find("%-%-%# Main") then --paste-into-project format
data = data.."--# " --add new file tag to end in order to capture last file
for name, file in data:gmatch("(%w+)\
(.-)\
%-%-%# ") do --capture each name and file
saveProjectTab(name, file)
print("Saved", name)
end
else --put it all in one tab
saveProjectTab("Main", data)
end
load(data)() --load the file
setup() --run it
end
local function failure(error)
print("Error", error)
end
http.request(linkRawCode, success, failure)
@glwhart - there have been many posts on using Dropbox for backup of files. I’ll try to cover this .On the root of Dropbox there is a folder called Apps (on mine) within that folder any external package (Codea in this case) can add a package root folder - so I have a Codea folder there. You can add any other folders/files in that folder. Most files there will be visible to Codea provided they have a recognised file type. Files in folders will not be visible but can still be accessed if you use an absolute address.
Codea keeps a duplicate copy of visible files in the Codea root on your iPad. This is accessible via the Asserts option from the top left button on the Codea main window. When you change the Dropbox folder contents (remote) you need to sync the iPad Dropbox folder from the top menu in the Codea root folder.
Try it out and if you have problems we can guide you through it.
I know it’s a bit outdated, but still, the old wiki tells, that, “[a]t the moment, there is not an elegant answer to copying code to and from Codea.”. But you can try doing all the options presented above (or below) this post.
Personally I was fine with storing all the code in a hub like pastebin, and then just re-downloading the code this way.
Here’s my latest backup/restore program. It created a backup file of my 578 projects in less than a second. Once you create a backup file, you can restore all or selected projects. This saves the backup file in the Codea Dropbox folder where you can then sync it with the Dropbox app. When I got a new iPad, I synced the new iPad with the Dropbox app to get the backup file into the Codea Dropbox folder on the new iPad. I then emailed a copy of the backup project, which should be saved separately, from my old iPad to the new one. I selected restore all projects and unselected the backup project name. You can’t restore a running project or you’ll get a Codea error and the restore will stop. It took about a second or so to create my 578 Codea projects on the new iPad.
When the backup is run, it creates a backup file named bkAyymmdd-hhmm where yymmdd is the year, month, day and hhmm is the hour and minute that the file was created. You can do backups as often as you want as long as you wait at least a minute.
This only saves the Codea projects. If you have assets or images or anything other than the project, those aren’t saved.
I’ve used various versions of this code to save and restore projects thru the years. The only time it crashed was when I tried to restore the backup project which you can’t do. You can’t restore a running project. I did that just to see what would happen.
displayMode(FULLSCREEN)
function setup()
delay=5
pns="PROJ".."NAME".."START" -- project name start
pne="PROJ".."NAME".."END" -- project name end
tns="TAB".."NAME".."START" -- tab name start
tne="TAB".."NAME".."END" -- tab name end
te="TAB".."END" -- tab end
pe="PROJ".."END" -- project end
bk1,bk2,bk3,bk4="","","",""
msg1=""
m1=button(WIDTH/2,HEIGHT-100,200,50,"Create a backup",createBkup)
m2=button(WIDTH/2,HEIGHT-200,200,50,"Select a backup",getBkups)
m3=button(WIDTH/2,HEIGHT-300,200,50,"Exit",exit)
b1=button(190,HEIGHT-200,180,50,"Turn all projects on.",allOn)
b2=button(190,HEIGHT-260,180,50,"Turn all projects off.",allOff)
b3=button(190,HEIGHT-360,180,50,"Allow overwrite. OFF",allowOverwrite)
b5=button(190,HEIGHT-520,180,50,"Restore selected items",restore)
b6=button(190,100,180,50,"Return to menu",retn)
func=menu
end
function draw()
background(40, 40, 50)
func()
end
function touched(t)
if t.state==ENDED then
if func==menu then
m1:touched(t)
m2:touched(t)
m3:touched(t)
elseif func==showBkups then
for a,b in pairs(bkupTab) do
if math.abs(t.x-WIDTH/2)<100 and math.abs(t.y-(HEIGHT-a*75+dy))<25 then
selectedBackupFile=b
func=getProjects
end
end
b6:touched(t)
elseif func==showProjects then
for a,b in pairs(projTab) do
if math.abs(t.x-WIDTH/2)<100 and math.abs(t.y-(HEIGHT-a*75+dy))<25 then
b.sel=not b.sel
end
end
b1:touched(t)
b2:touched(t)
b3:touched(t)
b5:touched(t)
b6:touched(t)
elseif func==showRestoreTable then
b6:touched(t)
end
end
if t.state==MOVING then
if func==showProjects or func==showRestoreTable then
if t.x<100 or t.x>WIDTH-100 then
sp=1
if t.y<HEIGHT/2 then
sp=20
end
dy=dy+t.deltaY*sp
if dy<0 then
dy=0
end
end
end
end
end
function menu()
fill(255)
m1:draw()
m2:draw()
m3:draw()
text(bk1,WIDTH/2,300)
text(bk2,WIDTH/2,260)
text(bk3,WIDTH/2,220)
text(bk4,WIDTH/2,180)
end
function exit()
close()
end
function retn()
msg1=""
func=menu
end
function createBkup()
if delay>0 then
func=createBkup
text("Creating backup",WIDTH/2,HEIGHT/2)
delay=delay-1
return
end
local proj=listProjects("Documents")
local t=os.date("*t")
backupName=string.format("bkA%02d%02d%02d-%02d%02d",
t.year%100,t.month,t.day,t.hour,t.min)
local temp={}
local dt=os.date()
local cnt=0
table.insert(temp,"BKUP==START.."..dt)
for a,b in pairs(proj) do
lst=listProjectTabs(b)
cnt=cnt+1
table.insert(temp,pns.."=="..b.."=="..pne)
for c,d in pairs(lst) do
table.insert(temp,tns.."=="..d.."=="..tne)
table.insert(temp,readProjectTab(b..":"..d))
table.insert(temp,"=="..te)
end
table.insert(temp,"=="..pe)
end
table.insert(temp,"BKUP==END")
local str=table.concat(temp,"\
")
bk1=backupName
bk2=dt
bk3="Projects saved = "..cnt
bk4="File size = "..#str.." bytes"
saveText("Dropbox:"..backupName,str)
delay=5
func=menu
end
function getBkups()
bk1,bk2,bk3,bk4="","","",""
bkupTab={}
showBackupTable=true
dy=0
local lst=assetList("Dropbox")
table.sort(lst)
for a,b in pairs(lst) do
if string.find(b,"bk") then
table.insert(bkupTab,b)
end
end
func=showBkups
end
function showBkups()
for a,b in pairs(bkupTab) do
sprite("Cargo Bot:Dialogue Button",WIDTH/2,HEIGHT-a*75+dy,200,50)
text(b,WIDTH/2,HEIGHT-a*75+dy)
end
b6:draw()
end
function getProjects()
text("Please wait, getting a list of all projects",WIDTH/2,HEIGHT/2)
projTab={}
local name=selectedBackupFile
bkupFile=readText("Dropbox:"..name)
if bkupFile==nil then
alert("No backup file selected.","ERROR")
return
end
local sss=pns.."==(.-)=="..pne
for projName,proj in string.gmatch(bkupFile,sss) do
table.insert(projTab,{proj=projName,sel=false,res=""})
end
dy=0
func=showProjects
end
function showProjects()
text("Tap a project to select or unselect it.",WIDTH/2,HEIGHT-20+dy)
for a,b in pairs(projTab) do
tint(255)
if b.sel then
tint(0, 255, 0, 255)
end
sprite("Cargo Bot:Dialogue Button",WIDTH/2,HEIGHT-a*75+dy,200,50)
fill(255)
text(b.proj,WIDTH/2,HEIGHT-a*75+dy)
if b.res~="" then
sprite("Cargo Bot:Dialogue Button",575,HEIGHT-a*75+dy,150,50)
text(b.res,575,HEIGHT-a*75+dy)
end
end
tint(255)
b1:draw()
b2:draw()
b3:draw()
b5:draw()
b6:draw()
scrollArea()
text(msg1,200,200)
end
function scrollArea()
fill(97, 229, 165, 100)
rect(0,HEIGHT/2+20,100,HEIGHT)
rect(0,0,100,HEIGHT/2-20)
rect(WIDTH-100,HEIGHT/2+20,100,HEIGHT)
rect(WIDTH-100,0,100,HEIGHT/2-20)
fill(255)
text("SLOW\
SCROLL\
AREA",50,HEIGHT*.75)
text("FAST\
SCROLL\
AREA",50,HEIGHT*.25)
text("SLOW\
SCROLL\
AREA",WIDTH-50,HEIGHT*.75)
text("FAST\
SCROLL\
AREA",WIDTH-50,HEIGHT*.25)
end
function allOn()
for a,b in pairs(projTab) do
b.sel=true
end
end
function allOff()
for a,b in pairs(projTab) do
b.sel=falss
end
end
function allowOverwrite(self)
Allow_overwrite=not Allow_overwrite
if Allow_overwrite then
self.name="Allow overwrite. ON"
self.col=color(255,0,0)
else
self.name="Allow overwrite. OFF"
self.col=color(255)
end
end
function restore()
resTab={}
msg1=""
if projTab==nil or selectedBackupFile=="" then
alert("No projects selected.","ERROR")
return
end
dy=0
cnt=0
for a,b in pairs(projTab) do
if b.sel then
cnt=cnt+1
pname=b.proj
restoreProject()
end
end
if cnt>0 then
alert("Check for error messages.","RESTORE COMPLETE")
else
alert("Nothing selected for restore.","ERROR")
return
end
allOff()
if Allow_overwrite then
allowOverwrite(b3)
end
dy=0
func=showRestoreTable
end
function restoreProject()
name=pname
local sss=pns.."==(.-)=="..pne.."\
(.-)=="..pe
if hasProject(name) then
if Allow_overwrite then
deleteProject(name)
else
table.insert(resTab,{proj=name,res="Overwrite OFF"})
return
end
end
if not hasProject(name) then
createProject(name)
for projName,proj in string.gmatch(bkupFile,sss) do
if name==projName then
getTab(proj)
end
end
table.insert(resTab,{proj=name,res="Restored"})
end
end
function getTab(proj)
local sss=tns.."==(%g+)=="..tne.."\
(.-)\
=="..te
for tabName,tab in string.gmatch(proj,sss) do
saveProjectTab(name..":"..tabName,tab)
end
end
function showRestoreTable()
for a,b in pairs(resTab) do
sprite("Cargo Bot:Dialogue Button",400,HEIGHT-a*75+dy,200,50)
fill(255)
text(b.proj,400,HEIGHT-a*75+dy)
sprite("Cargo Bot:Dialogue Button",575,HEIGHT-a*75+dy,150,50)
text(b.res,575,HEIGHT-a*75+dy)
end
b6:draw()
scrollArea()
end
button=class()
function button:init(x,y,w,h,n,f)
self.x=x
self.y=y
self.w=w
self.h=h
self.name=n
self.func=f
self.col=color(255)
end
function button:draw()
sprite("Cargo Bot:Dialogue Button",self.x,self.y,self.w,self.h)
fill(self.col)
text(self.name,self.x,self.y)
end
function button:touched(t)
if math.abs(t.x-self.x)<self.w/2 and math.abs(t.y-self.y)<self.h/2 then
self.func(self)
end
end
@glwhart - I can vouch for the backup system that @dave1707 has developed. I have been using this for a few months. The options are improving all the time, the selected project menu that @Anatoly describes is very new and I have used several times for backing up individual files. I suggest you try them all to see which you prefer.
I’ve created a Wiki Article on this. Read in the link attached below.