eclipsesource / tabris-js

Create native mobile apps in JavaScript or TypeScript.
https://tabrisjs.com
BSD 3-Clause "New" or "Revised" License
1.4k stars 170 forks source link

Support atob and btoa #899

Open trevorwat opened 8 years ago

trevorwat commented 8 years ago

Hi, While using the cordova-plugin-file I have found an inconsistency between IOS and Android. Android reads binary files as array buffer's fine, but IOS does not (I'll then be using JPEGJS to decode it into ImageData and write it to a canvas.. this works ok on Android but I can't read in the binary image data in IOS).

Here's some sample code that works in the scratchpad to illustrate the problem... it extends the file browser to allow reading image (png files as I the demo app has some easy to find png's we can use) and just outputs to the console when it has worked.


var currentDirectory;

tabris.create("Page", {
    title: "Using the Cordova file plugin...",
    topLevel: true,
    background: "#fff"
}).once("appear", createExample).open();

function createExample(page) {
  var rootDirMappings = [
    {name: "cordova.file.applicationDirectory", value: cordova.file.applicationDirectory},
    {name: "cordova.file.applicationStorageDirectory", value: cordova.file.applicationStorageDirectory}
  ];

  var rootDirPickerLabel = tabris.create("TextView", {
    layoutData: {left: 16, top: 8, right: 16},
    text: "Cordova Filesystem Entry Point",
    textColor: "#000088"
  }).appendTo(page);

  var rootDirPicker = tabris.create("Picker", {
    layoutData: {left: 16, top: [rootDirPickerLabel, 0], height: 48, right: 16},
    items: rootDirMappings.map(function(item) {return item.name;}),
    selectionIndex: 0
  }).appendTo(page);

  var urlBar = tabris.create("Composite", {
    layoutData: {left: 0, right: 0, top: [rootDirPicker, 0], height: 48},
  }).appendTo(page);

  var currentDirectoryView = tabris.create("TextInput", {
    layoutData: {left: 16, top: 0, right: [0, 80]},
    font: "16px",
    editable: false,
    autoCorrect: false,
    text: currentDirectory
  }).appendTo(urlBar);

  var upButton = tabris.create("Button", {
    layoutData: {left: [currentDirectoryView, 16], right: 16, top: 0},
    text: "Up",
    enabled: false
  }).appendTo(urlBar);

  var scrollView = tabris.create("ScrollView", {
    direction: "vertical",
    layoutData: {left: 0, top: [urlBar, 16], right: 0, bottom: 0}
  }).appendTo(page);

  var success = function(param) {
    console.log("using directory:\n" + JSON.stringify(param));
    var directoryReader = param.createReader();
    console.log("directoryReader:\n" + JSON.stringify(directoryReader));
    directoryReader.readEntries(function(result) {
      result.forEach(function (entry) {
        var row = tabris.create("Composite", {
          layoutData: {left: 0, right: 0, top: ["prev()", 1], height: 72},
          background: "#ddd"
        }).appendTo(scrollView);
        var dirEntryView = tabris.create("TextView", {
          layoutData: {left: 16, right: 16, centerY: 0},
          font: "10px",
          text: entry.fullPath,
          markupEnabled: true
        }).appendTo(row);
        if(entry.isDirectory) {
          dirEntryView.set("font", "bold 12px");
          dirEntryView.set("textColor", "blue");
          dirEntryView.on("tap", function() {
            console.log("tapped: " + entry.fullPath);
            changeDir(entry.nativeURL);
          });
        }
        if(entry.fullPath.indexOf(".png") != -1) {
          dirEntryView.set("font", "bold 12px");
          dirEntryView.set("textColor", "green");
          dirEntryView.on("tap", function() {
            console.log("tapped: " + entry.fullPath);
                  entry.file(function (entry) {
                      var reader = new FileReader();

                      reader.onloadend = function (e) {
                          console.log("file reading ended", this);
                          console.log(this.result);
                          //android reaches here and has the binary file data.. IOS does not
                      };

                      console.log("file reading about to start", this);

                      reader.readAsArrayBuffer(entry);
                      // IOS fails to in here with "can't find  variable atob" .. Android works ok

                      console.log("file reading about to started", this);
                  }, console.log("erre", entry));

        });
        }
      });
    });
  };
  var error = function(param) {console.log('== error \"' + param + '\"');};

  function changeDir(dir) {
    currentDirectory = dir;
    console.log("====\nCURRENT DIRECTORY:\n" + currentDirectory);
    currentDirectoryView.set("text", currentDirectory);
    scrollView.children().dispose();
    window.resolveLocalFileSystemURL(currentDirectory, success, error);
  }

  rootDirPicker.on("select", function(picker, selection, options) {
    changeDir(rootDirMappings[options.index].value);
  });

}
mpost commented 8 years ago

Thanks for your feedback. We are currently in the progress of extending TypedArray support on iOS. Please stay tuned for that.

patrykmol commented 8 years ago

Hello. There is an issue in JavaScriptCore engine (that is WebKit) https://bugs.webkit.org/show_bug.cgi?id=158576. It has been closed recently but there is no telling when they merge it and release it. I would file an issue in Cordova bug tracker. Closing for now.

jkrause commented 8 years ago

We can provide a fix in our iOS implementation in the mean time, probably in the next couple of days.

jkrause commented 8 years ago

A workaround for you until we support atob, btoa on iOS is to include a dependency to base64 in your package.json

  "dependencies": {
    "tabris": "1.8.0",
    "Base64": "^0.3.0"
  }

and require it before using the file plugin, e.g. like this:

if(device.platform === "iOS") {
    var base64 = require('base64');
    global.btoa = base64.btoa;
    global.atob = base64.atob;
}

See also

ralfstx commented 7 years ago

The functions atob and atob should be available in the global JS context. The implementations are small, so we should include shims.

mpost commented 6 years ago

The functions are available in iOS as can be seen here: https://caniuse.com/#search=btoa

Closing as "no action needed".

cpetrov commented 3 years ago

This issue was closed by mistake (see https://github.com/eclipsesource/tabris-js/issues/2071). Reopening.