Skip to content

Commit

Permalink
Implement platform file import/export features.
Browse files Browse the repository at this point in the history
  • Loading branch information
UtkarshSiddhpura committed Aug 20, 2024
1 parent 5fddd83 commit 96ee678
Show file tree
Hide file tree
Showing 10 changed files with 721 additions and 7 deletions.
2 changes: 1 addition & 1 deletion v2/js/modules/activities.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ define(["sugar-web/datastore"], function (datastore) {

// Test if activity is generic
activities.isGeneric = function(activity) {
return (activity == genericActivity);
return activity.directory === "icons" && activity.icon === "application-x-generic.svg";
};
activities.genericActivity = function() {
return genericActivity;
Expand Down
115 changes: 115 additions & 0 deletions v2/js/modules/file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
define(["platform/handler"], function (platform) {
const file = {};

// Write a new file
file.writeFile = async function (directory, metadata, content) {
let binary = null;
let text = null;
let extension = "json";
let title = metadata.title;
let mimetype = "application/json";

if (metadata && metadata.mimetype) {
mimetype = metadata.mimetype;
extension = getFileExtension(mimetype);
if (mimetype.startsWith("text/")) {
text = content;
} else {
binary = base64DecToArr(
content.substr(content.indexOf("base64,") + 7)
).buffer;
}
} else {
text = JSON.stringify({ metadata: metadata, text: content });
}

let filename = title;
if (!filename.endsWith(`.${extension}`)) {
filename += `.${extension}`;
}
await platform.saveFile({
filename,
text,
binary,
mimetype,
directory,
});
return filename;
};

function getFileExtension(mimetype) {
const mimetypeExtensions = {
"image/jpeg": "jpg",
"image/png": "png",
"audio/wav": "wav",
"video/webm": "webm",
"audio/mp3": "mp3",
"audio/mpeg": "mp3",
"video/mp4": "mp4",
"text/plain": "txt",
"application/pdf": "pdf",
"application/msword": "doc",
"application/vnd.oasis.opendocument.text": "odt",
"text/csv": "csv",
};

return mimetypeExtensions[mimetype] || "bin";
}

function base64DecToArr(sBase64, nBlocksSize) {
var sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""),
nInLen = sB64Enc.length,
nOutLen = nBlocksSize
? Math.ceil(((nInLen * 3 + 1) >> 2) / nBlocksSize) * nBlocksSize
: (nInLen * 3 + 1) >> 2,
taBytes = new Uint8Array(nOutLen);
for (
var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0;
nInIdx < nInLen;
nInIdx++
) {
nMod4 = nInIdx & 3;
nUint24 |=
b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << (6 * (3 - nMod4));
if (nMod4 === 3 || nInLen - nInIdx === 1) {
for (
nMod3 = 0;
nMod3 < 3 && nOutIdx < nOutLen;
nMod3++, nOutIdx++
) {
taBytes[nOutIdx] =
(nUint24 >>> ((16 >>> nMod3) & 24)) & 255;
}
nUint24 = 0;
}
}
return taBytes;
}
// Decoding functions taken from
// https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding
function b64ToUint6(nChr) {
return nChr > 64 && nChr < 91
? nChr - 65
: nChr > 96 && nChr < 123
? nChr - 71
: nChr > 47 && nChr < 58
? nChr + 4
: nChr === 43
? 62
: nChr === 47
? 63
: 0;
}

// Ask the user a set files and write it to datastore
file.askAndReadFiles = async function () {
await platform.readFile();
};

// Open the content as a document in a new Window
file.openAsDocument = function (metadata, text) {
platform.openAsDocument(metadata, text);
};

return file;
});
62 changes: 62 additions & 0 deletions v2/js/modules/platform/desktop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
define(["platform/shared"], function ({ writeFileToStore }) {
const electron = require("electron");
const ipc = electron.ipcRenderer;
function saveFileElectron({
filename,
text,
binary,
mimetype,
extension,
directory,
}) {
return new Promise((resolve, reject) => {
ipc.removeAllListeners("save-file-reply");

ipc.send("save-file-dialog", {
directory,
filename,
mimetype,
extension,
text,
binary,
});

ipc.once("save-file-reply", (event, arg) => {
if (arg.err) {
reject(new Error(arg.err));
} else {
resolve();
}
});
});
}

function readFileElecton() {
ipc.removeAllListeners("choose-files-reply");
ipc.send("choose-files-dialog");

return new Promise((resolve, reject) => {
ipc.once("choose-files-reply", (event, file, err, text) => {
if (err) {
reject(err);
console.erro("Error in readFileElecton:", error);
} else {
writeFileToStore(file, text);
resolve();
}
});
});
}

// function openDocInElectron(metadata, text) {
// const shell = electron.shell;
//
// ipc.removeAllListeners("create-tempfile-reply");
// ipc.send("create-tempfile", { metadata, text });
// ipc.on("create-tempfile-reply", function (event, file) {
// // Open in a shell
// shell.openExternal("file://" + file);
// });
// }
return { saveFileElectron, readFileElecton };
});
35 changes: 35 additions & 0 deletions v2/js/modules/platform/handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
define(["platform/mobile", "platform/desktop", "platform/web"], function (
{ saveFileMobile, openDocInMobile },
{ saveFileElectron, readFileElecton },
{ saveFileWeb, readFileWeb, openDocInWeb }
) {
const PLATFORM = sugarizer.getClientPlatform();

// Map functions
const platformActions = {
saveFile: {
[sugarizer.constant.webAppType]: saveFileWeb,
[sugarizer.constant.mobileType]: saveFileMobile,
[sugarizer.constant.desktopAppType]: saveFileElectron,
},
readFile: {
[sugarizer.constant.webAppType]: readFileWeb,
[sugarizer.constant.mobileType]: readFileWeb, //web works for mobile
[sugarizer.constant.desktopAppType]: readFileElecton,
},
openAsDocument: {
[sugarizer.constant.webAppType]: openDocInWeb,
[sugarizer.constant.mobileType]: openDocInMobile,
[sugarizer.constant.desktopAppType]: openDocInWeb, //web works for desktop
},
};

const platform = new Proxy(platformActions, {
get:
(target, prop) =>
(...args) =>
target[prop][PLATFORM](...args),
});

return platform;
});
97 changes: 97 additions & 0 deletions v2/js/modules/platform/mobile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
define(function () {
async function saveFileMobile({ filename, text, binary, mimetype }) {
const cordovaFileStorage = platform.ios
? cordova.file.documentsDirectory
: cordova.file.externalRootDirectory;

try {
const directory = await new Promise((resolve, reject) => {
window.resolveLocalFileSystemURL(
cordovaFileStorage,
resolve,
reject
);
});

const file = await new Promise((resolve, reject) => {
directory.getFile(filename, { create: true }, resolve, reject);
});

const fileWriter = await new Promise((resolve, reject) => {
file.createWriter(resolve, reject);
});

fileWriter.seek(fileWriter.length);

await new Promise((resolve, reject) => {
fileWriter.onwriteend = resolve;
fileWriter.onerror = reject;

if (text) {
const blob = new Blob([text], { type: mimetype });
fileWriter.write(blob);
} else {
fileWriter.write(binary);
}
});

return file.fullPath;
} catch (error) {
throw new Error(`Failed to save file: ${error.message}`);
}
}

function openDocInAndroid(metadata, text) {
const cordovaFileStorage = enyo.platform.ios
? cordova.file.documentsDirectory
: cordova.file.externalCacheDirectory;

window.resolveLocalFileSystemURL(
cordovaFileStorage,
function (directory) {
directory.getFile(
"sugarizertemp",
{ create: true, exclusive: false },
function (file) {
if (!file) {
return;
}

file.createWriter(function (fileWriter) {
fileWriter.seek(fileWriter.length);
const blob = base64toBlob(metadata.mimetype, text);
fileWriter.write(blob);

// Open in the file system
const filename =
cordovaFileStorage + "sugarizertemp";
cordova.InAppBrowser.open(filename, "_system");
});
}
);
}
);
}
function openDocInIOS(metadata, text) {
const blob = base64toBlob(metadata.mimetype, text);
const blobUrl = URL.createObjectURL(blob);
cordova.InAppBrowser.open(
blobUrl,
"_blank",
"location=no,closebuttoncaption=" + l10n.get("Ok")
);
}

function openDocInMobile(metadata, text) {
if (
sugarizer.constant.platform.android ||
sugarizer.constant.platform.androidChrome
) {
openDocInAndroid(metadata, text);
} else {
openDocInIOS(metadata, text);
}
}

return { saveFileMobile, openDocInMobile };
});
Loading

0 comments on commit 96ee678

Please sign in to comment.