UNPKG

afterwriting

Version:

Post-processing tools for Fountain screenplays

365 lines (327 loc) 11.7 kB
define(function(require) { var client_id = '540351787353-3jf0j12ccl0tmv2nbkcdncu0tuegjkos.apps.googleusercontent.com', scope = ['https://www.googleapis.com/auth/drive'], $ = require('jquery'), fn = require('utils/fn'), module = {}; module.init = function() { if (window.location.protocol !== 'file:') { var tag = document.createElement('script'), script_tag = document.getElementsByTagName('script')[0]; tag.async = 1; tag.src = 'https://apis.google.com/js/client.js'; tag.onload = function() { gapi.load('auth'); }; script_tag.parentNode.insertBefore(tag, script_tag); } }; module.is_available = function() { return !!window.gapi && window.location.protocol !== 'file:'; }; /** * Authorize and run the callback after authorization */ module.auth = function(callback) { gapi.auth.init(function() { authorize(true, handle_auth.bind(null, callback)); }); }; /** * Decorates method with auth call */ var auth_method = function(method) { return function() { var method_args = arguments; module.auth(function() { method.apply(null, method_args); }); }; }; /** * Authorize to gapi */ var authorize = function(immediate, callback) { gapi.auth.authorize({ client_id: client_id, scope: scope, immediate: immediate, }, callback); }; /** * Handle authorization. If authorization fails - tries to auth with immediate=false */ var handle_auth = function(callback, result) { if (result && !result.error) { module.access_token = result.access_token; callback(); } else { authorize(false, handle_auth_fallback.bind(null, callback)); } }; var handle_auth_fallback = function(callback, result) { if (result && !result.error) { module.access_token = result.access_token; callback(); } else { $.prompt('Google Drive authorization failed.'); } }; /** * Poll file content */ module.sync = function(fileid, timeout, sync_callback) { module.sync_timeout = setInterval(function() { module.load_file(fileid, function(content) { sync_callback(content); }); }, timeout); }; /** * Clears synchornization */ module.unsync = function() { clearInterval(module.sync_timeout); }; /** * Download content of the file by id */ var load_file = function(id, content_callback) { gapi.client.request({ path: '/drive/v2/files/' + id, method: 'GET' }).execute(function(response) { if (!response.error) { var url = response.exportLinks && response.exportLinks['text/plain'] ? response.exportLinks['text/plain'] : response.downloadUrl; // see: https://support.google.com/chrome/thread/29767271?hl=en url = url.replace("content.googleapis.com","www.googleapis.com"); download(url, function(content) { if (response.mimeType === "application/vnd.google-apps.document") { content = content.replace(/\r\n\r\n/g, '\r\n'); } content_callback(content, response.alternateLink, response.id); }); } else { $.prompt('Could not open the file!'); content_callback(undefined); } }); }; module.load_file = auth_method(load_file); /** * Fetch a file from a URL */ var download = function(url, callback) { $.ajax({ url: url, type: 'GET', beforeSend: function(xhr) { return xhr.setRequestHeader('Authorization', 'Bearer ' + module.access_token); }, success: callback }); }; /** * Upload a file */ var upload = function(options) { var blob = options.blob, filename = options.filename || 'newfile', callback = options.callback, parents = options.parents, fileid = options.fileid, convert = options.convert, isUpdate = fileid !== null; if (convert) { filename = filename.replace(/\.gdoc$/, ''); } var boundary = '-------314159265358979323846'; var delimiter = "\r\n--" + boundary + "\r\n"; var close_delim = "\r\n--" + boundary + "--"; var reader = new FileReader(); reader.readAsBinaryString(blob); reader.onload = function() { var contentType = blob.type || 'application/octet-stream'; var metadata = { 'mimeType': contentType }; if (!isUpdate) { metadata.title = filename; metadata.parents = parents || []; } var base64Data = btoa(reader.result); var multipartRequestBody = delimiter + 'Content-Type: application/json\r\n\r\n' + JSON.stringify(metadata) + delimiter + 'Content-Type: ' + contentType + '\r\n' + 'Content-Transfer-Encoding: base64\r\n' + '\r\n' + base64Data + close_delim; var path = '/upload/drive/v2/files/'; if (isUpdate) { path += fileid; } gapi.client.request({ 'path': path, 'method': isUpdate ? 'PUT' : 'POST', 'params': { 'uploadType': 'multipart', 'convert': convert }, 'headers': { 'Content-Type': 'multipart/mixed; boundary="' + boundary + '"' }, 'body': multipartRequestBody }).then( function(response) { callback(response.result); }, function(response) { $.prompt.close(); $.prompt(response.result.error.message); }); }; }; module.upload = auth_method(upload); /** * Generate list of files/folders */ var list = function(callback, options) { options = options || {}; options.error = options.error || function() {}; if (options.lazy) { callback(function(node, callback) { lazy_list(options, node, callback); }); return; } if (options.before) { options.before(); } var conflate_caller = function(conflate_callback, data) { var request_data = { path: '/drive/v3/files/', method: 'GET', params: { corpus: "user", fields: "nextPageToken,files/id,files/mimeType,files/name,files/trashed,files/explicitlyTrashed,files/parents,files/shared", q: 'trashed=false' + (options.folder ? " and '" + options.folder + "' in parents" : '') } }; if (data && data.nextPageToken) { request_data.params.pageToken = data.nextPageToken; } gapi.client.request(request_data).then( function(response) { conflate_callback(response.result); }, function(response) { $.prompt.close(); $.prompt(response.result.error.message); }); }; var conflate_tester = function(data) { return data.nextPageToken; }; var conflate_final = function(results) { var items = []; results.forEach(function(args) { items = items.concat(args[0].files); }); pull_callback(items); }; var pull_callback = function(items) { items = items.filter(function(item) { return !item.explicitlyTrashed && !item.trashed; }); var map_items = {}, root = { title: 'My Drive', id: 'root', isRoot: true, isFolder: true, children: [] }; items = items.filter(function(i) { return !options.pdfOnly || i.mimeType === "application/pdf" || i.mimeType === "application/vnd.google-apps.folder"; }); items.forEach(function(f) { map_items[f.id] = f; f.title = f.name; f.isFolder = f.mimeType === "application/vnd.google-apps.folder"; f.disabled = options.writeOnly && f.userPermission && f.userPermission.role && ["owner", "writer"].indexOf(f.userPermission.role) === -1; f.children = []; }); items.sort(function(a, b) { if (a.isFolder && !b.isFolder) { return -1; } else if (!a.isFolder && b.isFolder) { return 1; } return a.title > b.title ? 1 : -1; }); items.forEach(function(i) { if (!i.parents || i.parents.length === 0) { root.children.push(i); } else { i.parents.forEach(function(p) { var parent = map_items[p] || root; parent.children.push(i); }); } }); if (options.after) { options.after(); } callback(root); }; fn.conflate(conflate_caller, conflate_tester, conflate_final); }; module.list = auth_method(list); /** * Lazy-loading for the list * @param node - node to load * @param callback - callback run after children are loaded */ var lazy_list = function(options, node, callback) { var folder = node.id === '#' ? 'root' : node.id; var options = { folder: folder, pdfOnly: options.pdfOnly, writeOnly: options.writeOnly }; module.list(function(item) { var loaded_node = module.convert_to_jstree(item); callback.call(this, node.id === '#' ? loaded_node : loaded_node.children); }, options); }; /** * Convert a file/folder to a jstree node */ module.convert_to_jstree = function(item) { var children = item.children.map(module.convert_to_jstree); var result = { text: item.title + (item.disabled ? ' (no permissions)' : ''), id: item.id, data: item, type: item.isFolder ? 'default' : (item.shared ? 'shared-file' : 'file'), state: { opened: item.isRoot, disabled: item.disabled } }; if (children.length) { result.children = children; } else { result.children = item.isFolder; } return result; }; return module; });