App switching and Clock faces

Posted on
  • When you switch apps on the Bangle all the volatile state of the currently running app and of the current set of active widgets is lost. This is because the Bangle loader completely replaces the currently running app. This contributes greatly to the robustness of the Bangle since an error in an app is contained. However, it does mean that any widget state such as a Bluetooth connection is lost - see here.

    I frequently switch between different clock apps to increase visibility, for more information etc and it occurred to me that a full app context switch is not necessary. Consequently, I have developed multiclock an app which supports multiple clock faces. You can try it from my development repository app loader at jeffmer.github.io.

    It currently has three clock faces. Each clock face is described by a javascript file with the following format:

    (() => {
        function getFace(){
    	    function onSecond(){
    	       //draw digits, hands etc
    	    }
    	    function drawAll(){
    	       //draw background + initial state of digits, hands etc
    	    }
        	return {init:drawAll, tick:onSecond};
        }
        return getFace;
    })();
    

    For those familiar with the structure of widgets, this is similar, however, there is an additional level of function nesting. This means that although faces are loaded when the clock app starts running they are not instantiated until their getFace function is called, i.e. memory is not allocated to structures such as image buffer arrays declared in getFace until the face is selected. Consequently, adding a face does not require a lot of extra memory.

    The app at start up loads all files *.face.js. The simplest way of adding a new face is thus to load it into Storage using the WebIDE.

    I have not submitted a PR for the official repository as I am not sure that this is a problem that only I have due to the ANCS widget. However, it does allow very fast clock face switches.

  • @jeffmer, I like this very much!

    Browsing the code, I suggest this change:

    function stopdraw() {
      if(intervalRefSec) {intervalRefSec=clearInterval(intervalRefSec);}
    }
    
  • Thanks, will do.

  • That sounds like a really neat idea. With the ability to specify a 'dependency' in apps.json I guess it might be possible to make all the clock faces work in a similar way, but maybe that is overkill.

    I think at least initially this is something that'd be great in the main apps repository though if you were willing to do a PR.

  • You could remove one layer of function nesting by making each face a module.

    Each face would then follow the format

    exports.getFace = function (){
        function onSecond(){
           //draw digits, hands etc
        }
        function drawAll(){
           //draw background + initial state of digits, hands etc
        }
        return {init:drawAll, tick:onSecond};
    };
    

    And to load them you'd do something along the lines of

    let FACES = require("Storage").list(/\.face\.js$/).map(require);
    
  • My possibly mistaken impression was that Modules do not appear explicitly in Storage. For example, the gpsrec app uses the “graph” module which does not appear when you list files in the WebIDE.

  • Modules can come from a number of different places, including storage: https://www.espruino.com/Modules#from-storage

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

App switching and Clock faces

Posted by Avatar for jeffmer @jeffmer

Actions