No Util.writeStorageFile()?

Posted on
  • I've been working on my Bangle app and got to the point where I need to handle its configuration. I need to be able to read its current configuration, have the user modify it, then write it back.

    I started with the Data Storage Tutorial. In the interface.html file (which I can seem to get going - that's a separate issue) the code references Util.readStorageFile() and Util.eraseStorageFile().

    Going to the interface.js source I found that there is no Util.writeStorageFile(). Hopefully that's not too hard to add?

  • Hi - readStorageFile was added because StorageFile (as opposed to just the standard Storage) can be a bit of a pain to read. Since StorageFile is really for logging data (eg a file that keeps on growing) you probably shouldn't use it for settings, so writeStorageFile hasn't been needed so far.

    For settings, what you need is likely just to write to Storage, so you could just use the command:

    Puck.write(`\x10require("Storage").write­(${JSON.stringify(filename)},${JSON.stri­ngify(data)})\n`,callback);
    

    We could definitely build that into interface.js but it's not super painful to just do that directly in your interface.html code.

  • Thanks. There is quite a bit to learn! Writing then seems straightforward:

    Util.showModal("Saving...");
    Puck.write(`\x10require("Storage").write­(${JSON.stringify("myapp.json")},${JSON.­stringify(settings)})\n`,()=>{
        Util.hideModal();
    });
    

    However, the documentation implies that Storage.read/write are different and not compatible with StorageFile.read/write, so the example read code using StorageFile is inconsistent with using Storage.write. From my reading of the Puck code, the callback of Puck.write doesn't take any arguments, so I'm guessing the following WONT work:

    Util.showModal("Loading...");
    Puck.write(`\x10require("Storage").read(­${JSON.stringify("myapp.json")})\n`,data­=>{
      Util.hideModal();
      settings = JSON.parse(data);
    });
    

    This is rather confusing. It's a shame I can't see a way to try this with the emulator. I think I'll have to be patient and wait for the actual Bangle to turn up.

  • Hi, yes, you're right that StorageFile vs Storage is different - for the reading, write should return any data is printed, but I think what you want is just Puck.eval which returns the actual value returned by the function call:

    Puck.eval(`require("Storage").read(${JSO­N.stringify("myapp.json")})`,data=>{
      Util.hideModal();
      settings = JSON.parse(data);
    });
    

    But yes, I'm afraid this kind of thing is something it's not really possible to test in the emulator at the moment. Not long to wait for the Bangle now though!

  • OK. Thanks for your help. I'll just summarize all this for future reference:

    function loadSettings() {
      Util.showModal("Loading...");
      Puck.eval(`require("Storage").read(${JSO­N.stringify("myapp.json")})`,data=>{
        Util.hideModal();
        try {
          settings = JSON.parse(data);
        } catch {
          settings = defaultSettings;
        }
      });
    }
    function saveSettings() {
      Util.showModal("Saving...");
      Puck.write(`\x10require("Storage").write­(${JSON.stringify("myapp.json")},${JSON.­stringify(settings)})\n`,()=>{
        Util.hideModal();
      });
    }
    
  • Perfect - thanks!

    Just to say I added Util.writeStorage() and Util.readStorage() yesterday (I found myself doing it for another app and thought I might as well add it globally).

    While require("Storage").read(${JSON.stringify­("myapp.json")}) works perfectly for settings, in my case I had something in Storage that was binary, so the implementation I've used in the app loader transfers as base64 to avoid any corruption

  • I've now been advised that my attempt to use the above code in my app is working for reading the settings on the Bangle, but failing when attempting to write updated settings back to the Bangle. My code is:

    https://github.com/andrewgoz/BangleApps/­blob/1b9477be5d4c5af923b7ef435ae08b72117­1b7bf/apps/authentiwatch/interface.html#­L334

    The feedback was "I get an (nearly) empty authentiwatch.json file (consists of a few zeros)".

    I cannot investigate this myself as I have yet to receive my Bangle.

  • It turns out the Puck.write() function requires a particular structure to the JSON, namely:

    Uncaught TypeError: If specifying an object, it must be of the form {data : ..., count : N} or {callback : fn}
    

    I've just updated my app to meet this requirement...

  • Just posted on GitHub but I don't believe that is the case. Puck.write doesn't need that, but I think maybe you were passing an array to require("Storage").write(...) - which would then be interpreted as binary data. If you use .writeJSON you'll be good.

  • I've been working on my Bangle app and got to the point where I need to handle its configuration.

    Sounds like you just want to make a settings menu. Read a few options at start up in your app. Allow the user to change them via the settings app. This is done by creating an app.settings.js bit of code. Have a look at the Pastel app which does this.

  • Sounds like you just want to make a settings menu. Read a few options at start up in your app. Allow the user to change them via the settings app

    No, entering 2FA token settings on the watch would be a nightmare. You need to accurately type a string of 32 essentially random alphanumeric characters for each token. That's only practical on a phone/tablet or PC. Even better, a phone/tablet/PC usually has a camera for scanning a QR code representing the token.

    If you use .writeJSON you'll be good.

    I will look into that.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

No Util.writeStorageFile()?

Posted by Avatar for andrewg_oz @andrewg_oz

Actions