XFC 1.3.4 backups and ... Folders!

Hello all.
For backups and sharing we have a fantastic tool : CC.
However, when.

  • you have no wifi,
  • you just want a quick work backup,
  • you dont want your code to leave your ipad and go god-knows-where,
    now you’ll also have XFC to make quick local backups.
    And you can arrange them in folders too! Watch the video.

How to update to v1.3.4.

  • from v2.1: tab ‘download beta’ , the print will say ‘data received’, but the install button will not activate. This is bug. The file is here, but under the stable version name… (grrrr sorry for that). So now tap ‘install stable version’, this will install this new beta version instead.
  • from v3.xx : it should work… Maybe. Try the beta version, try the stable version, until you get the 1.3.4 installed.
    Sorty for this mess: i’ve transferred XFC in a new dedicated folder, and made the names more rationnal, but i managed all that very poorly. :frowning:

As usual, send me feedback (good or bad).

http://www.youtube.com/watch?v=KkY_UgvMW24

Very nice! Good work as always.

Notes:

  • The built-in updater failed to work as usual, however I had written my own using the URLs I saw in the code and that worked like a charm to get me to the latest version.

  • It appears that the updater in v1.3.4 is working, however i can’t be sure since I am on the latest version.

  • The backups with folders is a great new feature.

Thanks for the info. If too many people have problems to upgrade, i’ll post a specific updater. As you pointed out, it should work fine for next versions from now on.

Here is what I used to update:

--# Main
-- XFCUpdater

-- Use this function to perform your initial setup
function setup()
    XFCPROJECTNAME = "XFC"    -- Change this to whatever name your XFC is under or updating will fail
    
    url = {}
    url.host = "http://jmv38.comze.com/CODEAbis/XFC/"
    url.stable = "XFCBackup.txt"
    url.beta = "XFCbeta.txt"
    
    parameter.action("Update To Latest Stable Version", updateStable)
    parameter.action("Update To Latest Beta Version", updateBeta)
end

function updateStable()
    local success = function(data, status, headers)
        sound(SOUND_PICKUP, 15465)
        print("Successfully recieved stable version.")
        
        updateXFC(data)
    end
    
    print("Downloading latest stable version...")
    http.request(url.host .. url.stable, success, failed)
end

function updateBeta()
    local success = function(data, status, headers)
        sound(SOUND_PICKUP, 15465)
        print("Successfully recieved beta version.")
        
        updateXFC(data)
    end
    
    print("Downloading latest beta version...")
    http.request(url.host .. url.beta, success, failed)
end

function updateXFC(code)
    removePreviousVersion()
    
    saveNewVersion(code)
end

function saveNewVersion(code)
    print("Saving new version...")
    
    local tabs = parseForTabs(code)
    for id, tbl in ipairs(tabs) do
        print("Saving tab:", tbl.name)
        
        local tabName = XFCPROJECTNAME .. ":" .. tbl.name
        
        saveProjectTab(tabName, tbl.contents)
        
        print("Successfully saved tab:", tbl.name)
    end
    
    print("Successfully saved new version.")
end

function removePreviousVersion()
    print("Removing previous version...")
    
    local tabs = listProjectTabs(XFCPROJECTNAME)
    for id, tab in ipairs(tabs) do
        local newContent = nil
        if tab == "Main" then newContent = "" end -- Main can't be removed, clear it instead
        
        print("Removing tab:", tab)
        
        local tabName = XFCPROJECTNAME .. ":" .. tab
        
        saveProjectTab(tabName, newContent)
        
        print("Succesfully removed tab:", tab)
    end
    
    print("Successfully removed previous version.")
end

function parseForTabs(code)
    local tabIdentifier = "--" .. "# "    -- Can cause errors when together
    
    local tabName, tabContents
    
    local start, tabs = 0, {}
    
    while (start ~= nil) do
        local wcs, tns = code:find(tabIdentifier, start, true)
        local tne, tcs = code:find("\
", tns, true)
        tabName = code:sub(tns + 1, tne - 1)
        
        local tce, wke = code:find(tabIdentifier, tcs, true)
        local utce = tce
        if tce == nil then
            utce = code:len() + 1
        end
        tabContents = code:sub(tcs, utce - 1)
        
        start = tce
  
        table.insert( tabs, { name = tabName, contents = tabContents } )
    end
    
    return tabs
end


function failed(error)
    if error == "A connection failure occurred" then
        error = error .. ". Please check your internet connection."
    end
    
    print("Something went wrong:", error)
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)

    -- This sets the line thickness
    strokeWidth(5)

    -- Do your drawing here
    
end

Thanks. People can use it for this upgrade if it helps. But for next versions you should use the build in updater: this way i’ll be more capable to manage back-compatibilty problems.

I’m getting lots of errors when running this as a dependency to another project…

Line 204: cursor is nil

And when I try to save settings it causes an error

And when I hide the XFC by long press on FPS it causes an error

@JakAttak I dont have such problems here. It could be due to your update code. Do you have a Userdata tab? Your problem seem to linked to userdata saving.
Or it could be interactions with CC? I dont use it much, so i have not verified.

@JakAttak is your project called XFC? Saving works correctly only if you call the project XFC.

Yes my project is called XFC. Also, just to be safe i used the built in updater to get e latest beta. And I do have a userdata tab

Everything works from XFC itself, just not projects with XFC Dependency

Good. Try and run a copy of physics project, with a dependency to XFC. Does it work when you long press to hide XFC? It works for me. If it work for you, then what project cause the failure? Do you have other dependencies?

You are right physics works for me. The project causing the failure is one of my games. I will test all the dependencies to try and find the problem one

EDIT: it is the juice library that causes errors

@JakAttak if this library is public, i’ll load it and check what is going on. What can go wrong with XFC is:
1- if the draw() function adress is modifided during runtime.
2- same with touched().
3- if the startup of your project takes more than 1s.
For 1 and 2 there is nothing i can do. For 3 the startup time of XFC can be made longer. It has to start afer draw() and touched() are defined.

Anyone else has tried?

Btw, here is my ‘official’ loader:


-- XFCloader

function setup()
print("install XFC beta")
t = ElapsedTime
notFinished = true
local url = "http://jmv38.comze.com/CODEAbis/XFC/XFCbeta.txt"
local projectName = "XFC"
local list = listProjectTabs(projectName)
if #list == 0 then 
print("you must create a project named ".. projectName .." first!")
notFinished = false
return
end
p = ProjectLoader( url ,projectName)
print("request send,Codea will not seem alive for seconds. Be patient...")
tween.delay(0.1,p.load,p)
end

function draw()
if ElapsedTime>t+1 and notFinished then print("be patient...") t = ElapsedTime end
end

ProjectLoader = class()

function ProjectLoader:init(url,projectName)
self.url = url
self.projectName = projectName
end

function ProjectLoader:load()
    http.request( self.url, function(data)
        print("data received. Install will need 15s. Be patient...")
        tween.delay(0.3,function()
        local list = listProjectTabs(self.projectName)
        for i,tab in pairs(list) do
            if tab ~= "Main" and tab ~= "History"
            then 
                local tabName = self.projectName .. ":".. tab 
                if tab == "UserData" then self.userData = readProjectTab(tabName) end
                saveProjectTab(tabName,nil) 
            end
        end
        
        -- code from Mpilgrem
        local first, last = string.find("\
"..data, "\
%-%-#%s")
        if first then
            for s in string.gmatch(string.sub(data, last).."\
--# ", "(.-)\
%-%-#%s") do
                local tabName, tabContents = string.match(s, "(%w+)\
(.*)")
                saveProjectTab( self.projectName ..":"..tabName, tabContents)
            end
        end

        print("install in ".. self.projectName .." complete")
        notFinished = false
        end)
   end)
    
end

To answer a question from @Ignatz: ’ how you save files to subfolders, if you don’t mind sharing that…'.
So the answer is: there is no real subfolders. Everything is flat in /documents/. But each folder knows what it contains. So when i present it to you within XFC, i create a fake subfolder structure. To manage simply the tree structure, each file/folder has a name that will not change. When you rename a file/folder, you just change the username, the name under which XFC presents the file to you. So fake again. But who cares? What is important is not the disk structure, it is the virtual structure that you can see from XFC. Hope this is clear?

lol, thank you! ;))

Has anyone been using this backup functions since i released them?
I’ve been using it seriously the last 2 weeks:

  • it works.
  • i have saved more than 30 projects.
  • i have only 3 projects now, and i do everything from them.
  • It is really faster to manage many projects (like copies from the forum).
    The only weakness i’ve found:
  • some characters (special ones) do not work correctly when renaming a project.
  • you cant save a bugged project that doesnt run (codea stop cause of the error).
  • projects must have a draw function.
    I am currently reworking the code to structurize and cleanup for better maintenabiloty and reuse. It is a pleasant task since my understanding of the ‘super’ concept (see other discussion): the fonctions can really be made isolated and OO style, so my head doesnt explode due to nterractions.