fetch('https://www.bla.com/bla.json')
.then(function(response) { return response.json(); })
.then(function(responseObject) {
responseObject.forEach(function(el){
// Get JSON data and process image URL from there
var imgUrl = el.Photo;
var img = imgUrl.substring(imgUrl.lastIndexOf('/')+1,imgUrl.lastIndexOf('.')+4);
console.log(FileSystem.dataDirectory + "/" + img);
el.LocalPhoto = FileSystem.dataDirectory + "/" + img;
// If the file does not exist, fetch it and save it
FileSystem.exists(FileSystem.dataDirectory + "/" + img)
.then(function(x) {
console.log(x ? "it's there! =)" : "it's missing :/");
if (!x){
var oReq = new XMLHttpRequest();
oReq.open("GET", imgUrl, true);
oReq.responseType = "arraybuffer";
oReq.onload = function (oEvent) {
var arrayBuffer = oReq.response;
if (arrayBuffer) {
var path = FileSystem.dataDirectory + "/" + img;
FileSystem.writeBufferToFile(path, arrayBuffer);
}
};
oReq.send(null);
}
}, function(error) {
console.log("Unable to check if file exists");
});
});
});
You could mark nodes as busy from JavaScript like this (and use the UX class Busy to show a loading animation or low quality image as the first snippet you provided had)
A node is automatically marked as busy (meaning, WhileBusy evaluates to true) when any one of its children is doing something that takes time. Downloading the data for an Image does that too, for example.
This means that you don’t need to explicitly set a node as busy from JavaScript to use WhileBusy. You simply put it on the parent container of your Image tags and it will just work.
If, as you say, the images don’t exist at first, you should use a <WhileString Value="{pathToImage}" Equals=""> and show a placeholder image that you bundle with the app. If the path is an Observable, you could change it to the real path once the image arrives.
Since tracks can change during run-time (e.g., you load more tracks or remove some), it has to be an Observable list of objects.
Each object in that list should hold the properties that you want to show in the UI, in your example those are title and localPhoto:
{
title: "This is a title for item",
localPhoto: "/some/path/to/file.png"
}
However, since you also want to be able to change the path to the image being shown, the localPhoto property can not be a simple string, so we need to make it an Observable:
{
title: "This is a title for item",
localPhoto: Observable("/some/path/to/file.png")
}
And then we can update any particular item in the tracks list, by setting the .value of the localPhoto Observable whenever your async fetch() for a particular image completes:
Thanks, was about to start using that, when I remembered I can force a redraw if I replace the observable. I just do that, does a redraw, and dont have to worry about that anymore.