Skip to content

Commit

Permalink
Handle downloads correctly in Cordova environment
Browse files Browse the repository at this point in the history
  • Loading branch information
skishore committed Apr 26, 2017
1 parent 1fa4f9a commit 479bf09
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 28 deletions.
57 changes: 48 additions & 9 deletions client/assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,52 @@ const kLoaded = new Promise((resolve, _) => onAssetsLoaded = resolve);

const kStartup = new Promise((resolve, _) => Meteor.startup(resolve));

const base64 = {
decode: (uri) => {
const d = (ch) => '%' + ('00' + ch.charCodeAt(0).toString(16)).slice(-2);
return decodeURIComponent(Array.from(atob(uri)).map(d).join(''));
},
encode: (data) => {
return btoa(encodeURIComponent(data).replace(
/%([0-9A-F]{2})/g, (match, x) => String.fromCharCode('0x' + x)));
},
};

// Input: a target filename and the data to download to it.
// Output: a Promise that resolves to a description of where to find the
// downloaded file: in Downloads, on web, or in ~/Inkstone on mobile.
const download = (filename, data) => {
return kStartup.then(() => new Promise((resolve, reject) => {
if (Meteor.isCordova) {
const fragments = [cordova.file.externalRootDirectory, 'Inkstone'];
const target = `${fragments.join('')}/${filename}`;
const success = () => resolve(target.substr('file://'.length));
fileWriteHelper(fragments, filename, data, success, reject);
} else {
const link = document.createElement('a');
link.href = `data:text/plain;charset:utf-8;base64,${base64.encode(data)}`;
link.download = filename;
link.click();
resolve('Downloads folder.');
}
}));
}

// Input: a list of path fragments in a Cordova filesystem, a file to write
// at the directory given by those fragments, the data to write to it,
// and two Promise "resolve/reject" callbacks to execute on completion.
const fileWriteHelper = (fragments, filename, data, resolve, reject) => {
getDirectoryEntry(fragments).then((entry) => {
entry.getFile(filename, {create: true}, (file) => {
file.createWriter((writer) => {
writer.onerror = reject;
writer.onwriteend = () => resolve(true);
writer.write(new Blob([data]), {type: 'text/plain'});
}, reject);
}, reject);
}).catch(reject);
}

const isImportedAsset = (asset) => {
return asset.startsWith('characters/') || asset.startsWith('lists/s/');
}
Expand Down Expand Up @@ -192,15 +238,7 @@ const writeAsset = (path, data) => {
const prefix = [cordova.file.dataDirectory, 'www', 'assets'];
const fragments = prefix.concat(path.split('/'));
const filename = fragments.pop();
return getDirectoryEntry(fragments).then((entry) => {
entry.getFile(filename, {create: true}, (file) => {
file.createWriter((writer) => {
writer.onerror = reject;
writer.onwriteend = () => resolve(true);
writer.write(new Blob([data]), {type: 'text/plain'});
}, reject);
}, reject);
}).catch(reject);
fileWriteHelper(fragments, filename, data, resolve, reject);
} catch (e) {
reject(e);
}
Expand Down Expand Up @@ -276,6 +314,7 @@ const kRadicals = readAsset('radicals.json')

export {
kCharacters,
download,
onAssetsLoaded,
readCharacter,
readItem,
Expand Down
21 changes: 2 additions & 19 deletions client/templates/settings/code.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* along with Inkstone. If not, see <http://www.gnu.org/licenses/>.
*/

import {readList, writeList} from '/client/assets';
import {download, readList, writeList} from '/client/assets';
import {Backdrop} from '/client/backdrop';
import {Lists} from '/client/model/lists';
import {clearTables} from '/client/model/persistence';
Expand Down Expand Up @@ -74,16 +74,6 @@ const confirmWithCode = (title, action) => {
Popup.show({title: title, template: template, buttons: buttons});
}

const decodeBase64 = window.decodeBase64 = (uri) => {
const d = (ch) => '%' + ('00' + ch.charCodeAt(0).toString(16)).slice(-2);
return decodeURIComponent(Array.from(atob(uri)).map(d).join(''));
}

const encodeBase64 = window.encodeBase64 = (data) => {
return btoa(encodeURIComponent(data).replace(
/%([0-9A-F]{2})/g, (match, x) => String.fromCharCode('0x' + x)));
}

const getDateString = () => {
const d = new Date();
const p = (x) => { const y = '' + x; return (y.length < 2 ? '0' : '') + y; }
Expand All @@ -101,13 +91,6 @@ const onError = (title) => (error) => {
Popup.show({buttons: buttons, text: `${error}`, title: title});
}

const startDownload = (data, filename) => {
const link = document.createElement('a');
link.href = `data:text/plain;charset:utf-8;base64,${encodeBase64(data)}`;
link.download = filename;
link.click();
}

const submitBackup = () => {
const filename = $('.popup input[type="text"]').val();
const database = JSON.parse(JSON.stringify(localStorage));
Expand All @@ -118,7 +101,7 @@ const submitBackup = () => {
const lists = _.keys(Lists.getImportedLists());
Promise.all(lists.map(readList)).then((values) => {
lists.map((x, i) => data.lists[x] = values[i]);
startDownload(JSON.stringify(data), filename);
download(filename, JSON.stringify(data));
Popup.hide();
}).catch(onError('Backup failed'));
}
Expand Down

0 comments on commit 479bf09

Please sign in to comment.