API Development

How to Access your CHANGELOG within your App to Implement a “What’s New” Feature

This guest post was authored by Adam Armstrong. Adam has been using Titanium since 2010 and is an Appcelerator Titan. He is the Manager of Mobile Technology at AmWINS Group and does freelance work via https://implicitli.com. You can follow him on Twitter at @adamtarmstrong.

Prerequisites

  • Alloy App
  • CHANGELOG.md file
  • changelog-parser npm package
  • alloy.jmk file

What is a CHANGELOG?

A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of a project.

Note: A CHANGELOG is not the same as a git commit log. A CHANGELOG should only contain info the end user needs to know regarding changes to the software.

Convert CHANGELOG to Markdown

Titanium ships with a CHANGELOG.txt file. Change the file extension to .md so we can leverage all of the features of Markdown.

Convert your CHANGELOG contents from plain text to Markdown

To programatically access the contents, we need to adopt a standard. One of the most widely adopted standards is keep a changelog. Visit that link for more detail, but here is a rough outline of how a release entry might look.

## 4.2.9-2019-02-13
### Added
- Added that great feature you've been waiting for
### Fixed
- Fixed that annoying bug everyone hated

 

Add the ‘changelog-parser’ npm package (we will use this to export our CHANGELOG to a JSON Object at compile time)

  • Simply run this to install the command-line version
    npm install -g changelog-parser
  • Open the file: **/app/alloy.jmk** (If it doesn’t exist, simply create one) and copy/paste this into that file
    task("pre:load", function(event, logger) {
       const execSync = require('child_process').execSync;
       const fs = require('fs');
       const path = require('path');
       //ensure directory exists
       const dir = path.join(process.cwd(), 'app', 'lib');
          if (!fs.existsSync(dir)) {
             logger.info(`Creating ${dir}`);
             fs.mkdirSync(dir);
          }
       //get ChangeLog and write to file
          const changelogObject = execSync("changelog-parser ./CHANGELOG.md").toString();
          const myFile = dir + '/changelog.json';
          fs.writeFileSync(myFile,changelogObject, 'utf8');
    });

Now, when we compile our Alloy app, before anything else is compiled, the “pre:load” task runs, ensures the /app/lib directory exists, and then parses the `CHANGELOG.md` file into a JSON Object saved into a new file, `changelog.json`.

For reference, here’s how the above CHANGELOG release looks after being converted to a JSON Object:

{
   "versions": [{
      "version": "4.2.9",
      "title": "4.2.9 - 2019-02-13",
      "date": "2019-02-13",
      "body": "### Added\n- Added that great feature you've been waiting for \n### Fixed\n- Fixed that annoying bug everyone hated",
      "parsed": {
         "_": [
            "Added that great feature you've been waiting for",
            "Fixed that annoying bug everyone hated"
         ],
         "Added": [
            "Added that great feature you've been waiting for"
         ],
         "Fixed": [
            "Fixed that annoying bug everyone hated"
         ]
      }
   }]
}

 

This gives you a Top Level Array `versions` with the first record [0] being the most recent version and each item in the Array includes:

  • `body` is a flattened list of features in markdown format
  • `parsed` is an array of features in plain text
  • `Added` is an array of “Added” features
  • `Fixed` is an array of “Fixed” features

Access your changelog.json file within your Mobile App

This is really straightforward. We simply get the file in the resourcesDirectory, read it, and then parse it as JSON.

var changelog = JSON.parse(Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory,'changelog.json').read());

 

Utilizing in your App

Where you go from here will greatly vary based on your app.

  • Determine a new version has been installed
  • On launch, you may want to get the current version installed using
    Ti.App.version
  • Then, compare against an already saved value of the last version that was installed using
    Ti.App.Properties.getString('lastAppVersionUsed');
  • If new version, then present a modal with the respective version array item in your changelog variable
    Ti.API.info("New Version:\nVersion: " + changelog.versions[0].version + "\nReleased: " + changelog.versions[0].date);

    Output:

    New Version:

    Version: 4.2.9

    Released: 2019–02–13

  • Whatever you do, don’t forget to update your saved value so that the user doesn’t get prompted again on the next launch.
    Ti.App.Properties.setString('lastAppVersionUsed', Ti.App.version);

You now have a structured CHANGELOG in Markdown that is not only in a “friendly” format for git repos, but also available as a JSON Object within your app.