From 552be268315d7dfe7f13b9b2fee6eb5aa11d9be6 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Tue, 8 Mar 2022 18:30:49 -0500 Subject: [PATCH] Working on rewrite version 3. Focus on caching and opening after download. --- app/index.html | 8 +- app/js/app_ui_misc.js | 4 +- app/js/app_v3.js | 223 +++++++++++++++++++- app/js/{app_helper.js => del app_helper.js} | 0 app/js/module_app.js | 10 +- config.json | 1 + index.js | 160 +++++++++++--- 7 files changed, 357 insertions(+), 49 deletions(-) rename app/js/{app_helper.js => del app_helper.js} (100%) diff --git a/app/index.html b/app/index.html index 216981d..c8f3d76 100644 --- a/app/index.html +++ b/app/index.html @@ -83,8 +83,9 @@ - - + + + @@ -103,7 +104,7 @@ const flask_env = 'development'; // 'development', 'production' const env = 'development'; // 'development', 'production' const app_env = 'development_local'; // 'development_local', 'development_remote' const api_env = 'development_local'; // 'development_local', 'development_remote' -const app_mode = 'onsite'; // null, 'default', 'onsite' +const app_mode = 'app'; // null, 'default', 'onsite', 'app' let client_account_id = app_config.account_id; console.log(client_account_id); @@ -114,6 +115,7 @@ const page_for = { 'event': event_id, 'event_location': event_location_id }; // console.log(page_for); const host_file_cache_path = app_config.host_file_cache_path; // 'file_cache/' +const host_file_temp_path = app_config.host_file_temp_path; // 'temp/' /* ***** **** *** ** * ### * ** *** **** ***** */ diff --git a/app/js/app_ui_misc.js b/app/js/app_ui_misc.js index e78b99b..fd412f5 100644 --- a/app/js/app_ui_misc.js +++ b/app/js/app_ui_misc.js @@ -158,9 +158,9 @@ function format_bytes(bytes, decimals = 2) { return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; } -function shorten_filename(filename) { +function shorten_filename(filename, max_length=45) { let length = filename.length; - let char_over = filename.length-45; + let char_over = filename.length-max_length; let new_filename = null; let wildcards = char_over; if (char_over > 0) { diff --git a/app/js/app_v3.js b/app/js/app_v3.js index e8e9aa6..9a49a9b 100644 --- a/app/js/app_v3.js +++ b/app/js/app_v3.js @@ -1,20 +1,225 @@ +'use strict'; +const os = require('os'); const path = require('path'); +const fs = require('fs'); const { ipcRenderer } = require('electron'); + +exports.load_config = function () { + console.log('*** Electron framework: load_config() ***'); + console.log('CWD: '+process.cwd()); + + let home_directory = require('os').homedir(); + console.log('Home: '+home_directory); + + let tmp_directory = require('os').tmpdir(); + console.log('Temporary: '+tmp_directory); + + let config = null; + let config_directory = null; + let default_config_path = path.join(process.cwd(),'config.json.default'); + let config_path = null; + + if (os.platform == 'darwin') { + config_directory = path.join(home_directory, 'Library/Application Support/OSIT'); + console.log('macOS config directory: '+config_directory); + } else if (os.platform == 'linux') { + config_directory = path.join(home_directory, '.config/OSIT'); + console.log('Linux config directory: '+config_directory); + } + + if (fs.existsSync(config_directory)) { + console.log('Config: '+config_directory); + config_path = path.join(config_directory, 'config.json'); + } else { + fs.mkdirSync(config_directory); + console.log('Config directory created: '+config_directory); + + //default_config_path = path.join(process.cwd(),'config.json.default'); + config_path = path.join(config_directory, 'config.json'); + fs.copyFileSync(default_config_path, config_path); + console.log('Default config file copied: '+config_directory); + } + + if (fs.existsSync(config_path)) { + console.log('Config path: '+config_path); + console.log('Config file (config.json) found under '+config_directory+'.'); + + config = JSON.parse(fs.readFileSync(config_path)); + console.log('Config file read.'); + } else if (!fs.existsSync(config_path)) { + fs.copyFileSync(default_config_path, config_path); + console.log('Default config file copied: '+config_directory); + + config = JSON.parse(fs.readFileSync(config_path)); + console.log('Config file read.'); + } else if (fs.existsSync('config.json')) { + //fs.copyFileSync(default_config_path, config_path); + //console.log('Default config file copied: '+config_directory); + + config = JSON.parse(fs.readFileSync('config.json')); + console.log('Config file (config.json) not found under '+config_directory+'. Using config in CWD.'); + console.log('Config file read.'); + + //console.log('Config file (config.json) not found under '+config_directory+'. Using config in CWD.'); + //config = JSON.parse(fs.readFileSync('config.json')); + } else { + //close(); + } + //console.log(config); + return config; +} + + +// exports.check_file_cache = async function ({host_file_cache_path, event_file_id, hash}) { +exports.check_file_cache = async function ({host_file_cache_path, event_file_id, hash}) { + console.log('*** Electron framework: check_file_cache() ***'); + console.log('Checking the local file cache against the remote server.'); + + event_file_id; // NOTE: This is the event_file.id_random or event_file.event_file_id_random + let hash_filename = hash+'.file'; + + let save_path = path.join(host_file_cache_path, hash_filename); + console.log(save_path); + + if (fs.existsSync(save_path)) { + console.log('Hashed file cache already exists: '+save_path); + return true; + } else { + console.log('Hashed file not found in local cache. Downloading file: '+save_path); + let endpoint = `/event/file/${event_file_id}/download`; + let result = await ipcRenderer.send('download_file', api_base_url, endpoint, save_path); // Must download file using main node.js thread. + console.log(result); + + return new Promise((resolve, reject) => { + ipcRenderer.once('download_file_reply', function(event, response){ + console.log(response); + return response; + }) + resolve(true); + }); + + // await ipcRenderer.once('download_file_reply', function(event, response){ + // console.log(response); + // return response; + // }); + + // result.then(function (response) { + // console.log('Downloaded!!!???'); + // return true; + // }).catch(function (error) { + // console.log(error); + // return false; + // }); + + // return result; + + // console.log(result); + // if (result) { + // return true; + // } else { + // return false; + // } + } +} + /* Updated 2022-03-07 */ // function open_local_file({hash, host_file_cache_path, filename}) { -function open_local_file({host_file_cache_path, hash, filename}) { +exports.open_local_file = async function ({host_file_cache_path, hash, host_file_temp_path, filename}) { + console.log('*** Electron framework: open_local_file() ***'); - console.log('*** open_local_file() ***'); - - // hash = this.getAttribute('data-hash_sha256'); - // let file_path = path.join(host_file_cache_path, hash); - // filename = this.getAttribute('data-filename'); console.log(host_file_cache_path); console.log(hash); - // console.log(file_path); console.log(filename); - // ipcRenderer.send('open_local_file', file_path, filename); - ipcRenderer.send('open_local_file', host_file_cache_path, hash, filename); + let result = await ipcRenderer.send('open_local_file', host_file_cache_path, hash, host_file_temp_path, filename); + console.log(result); + + return true; +} + + + + +async function check_file_cache({host_file_cache_path, event_file_id, hash}) { + console.log('*** Electron framework: check_file_cache() ***'); + console.log('Checking the local file cache against the remote server.'); + + event_file_id; // NOTE: This is the event_file.id_random or event_file.event_file_id_random + let hash_filename = hash+'.file'; + + let save_path = path.join(host_file_cache_path, hash_filename); + console.log(save_path); + + if (fs.existsSync(save_path)) { + console.log('Hashed file cache already exists: '+save_path); + return true; + } else { + console.log('Hashed file not found in local cache. Downloading file: '+save_path); + let endpoint = `/event/file/${event_file_id}/download`; + let result = await ipcRenderer.send('download_file', api_base_url, endpoint, save_path); // Must download file using main node.js thread. + console.log(result); + + return new Promise((resolve, reject) => { + ipcRenderer.once('download_file_reply', function(event, response){ + console.log(response); + return response; + }) + resolve(true); + }); + + // await ipcRenderer.once('download_file_reply', function(event, response){ + // console.log(response); + // return response; + // }); + + // result.then(function (response) { + // console.log('Downloaded!!!???'); + // return true; + // }).catch(function (error) { + // console.log(error); + // return false; + // }); + + // return result; + + // console.log(result); + // if (result) { + // return true; + // } else { + // return false; + // } + } +} + +async function open_local_file({host_file_cache_path, hash, host_file_temp_path, filename}) { + console.log('*** Electron framework: open_local_file() ***'); + + console.log(host_file_cache_path); + console.log(hash); + console.log(filename); + + let result = await ipcRenderer.send('open_local_file', host_file_cache_path, hash, host_file_temp_path, filename); + console.log(result); + + return true; +} + + +exports.check_file_cache_and_open_local_file = async function ({host_file_cache_path, event_file_id, hash, host_file_temp_path, filename}) { + console.log('*** Electron framework: check_file_cache_and_open_local_file() ***'); + console.log('Checking the local file cache against the remote server and then opening the local file.'); + + let check_file_cache_result = check_file_cache({host_file_cache_path: host_file_cache_path, event_file_id: event_file_id, hash: hash}); + + ipcRenderer.once('download_file_reply', function(event, response){ + console.log(response); + + let open_local_file_result = open_local_file({host_file_cache_path: host_file_cache_path, hash: hash, host_file_temp_path: host_file_temp_path, filename: filename}); + + return open_local_file_result; + }) + + + } \ No newline at end of file diff --git a/app/js/app_helper.js b/app/js/del app_helper.js similarity index 100% rename from app/js/app_helper.js rename to app/js/del app_helper.js diff --git a/app/js/module_app.js b/app/js/module_app.js index 96e0e2b..cc63158 100644 --- a/app/js/module_app.js +++ b/app/js/module_app.js @@ -69,8 +69,8 @@ exports.load_config = function () { } -exports.check_file_cache_v3 = async function (host_file_cache_path, event_file_id, hash) { - console.log('**** *** ** * FUNCTION: check_file_cache_v3 * ** *** ****'); +exports.check_file_cache = async function (host_file_cache_path, event_file_id, hash) { + console.log('**** *** ** * FUNCTION: check_file_cache (v3) * ** *** ****'); console.log('Checking the local file cache against the remote server.'); event_file_id; // NOTE: This is the event_file.id_random or event_file.event_file_id_random @@ -80,9 +80,9 @@ exports.check_file_cache_v3 = async function (host_file_cache_path, event_file_i console.log(save_path); if (fs.existsSync(save_path)) { - console.log('Local file already exists: '+save_path); + console.log('Hashed file cache already exists: '+save_path); } else { - console.log('File not found locally. Downloading file: '+save_path); + console.log('Hashed file not found in local cache. Downloading file: '+save_path); let endpoint = `/event/file/${event_file_id}/download`; ipcRenderer.send('download_file', api_base_url, endpoint, save_path); // Must download file using main node.js thread. } @@ -91,7 +91,7 @@ exports.check_file_cache_v3 = async function (host_file_cache_path, event_file_i } -exports.check_file_cache = async function () { +exports.check_file_cache_v1 = async function () { console.log('**** *** ** * FUNCTION: check_file_cache * ** *** ****'); console.log('Checking the local file cache against the remote server.'); diff --git a/config.json b/config.json index c19168b..0a6826f 100644 --- a/config.json +++ b/config.json @@ -38,6 +38,7 @@ "idb_event_file_check_period": 30000, "host_file_cache_path": "file_cache", "host_file_cache_check_period": 30000, + "host_file_temp_path": "temp", "display_arrangement": "mirror_and_extend", "display_builtin_resolution": "", "display_builtin_refresh": "", diff --git a/index.js b/index.js index fa97d21..bd6ef6e 100644 --- a/index.js +++ b/index.js @@ -95,36 +95,124 @@ app.on('activate', () => { // ipcMain.on('download_file', (event, api_base_url, api_endpoint, api_temporary_token, save_path) => { -ipcMain.on('download_file', (event, api_base_url, api_endpoint, save_path) => { +ipcMain.on('download_file', async (event, api_base_url, api_endpoint, save_path) => { console.log('*** call IPC download_file() ***'); // console.log('ipcMain on download_file: api_base_url='+api_base_url+' | api_temporary_token='+api_temporary_token); console.log('ipcMain on download_file: api_base_url='+api_base_url); // console.log(api_temporary_token); - console.log('ipcMain download and save file: '+api_endpoint+' -> '+save_path); + console.log('ipcMain download and save file: HTTP '+api_endpoint+' -> FILE '+save_path); - axios.defaults.baseURL = api_base_url; - axios.defaults.headers.common['Access-Control-Allow-Origin'] = '*'; // app_config.access_control_allow_origin; - axios.defaults.headers.common['content-type'] = 'application/json'; - axios.defaults.headers.common['x-aether-api-key'] = 'dFP6J9DVj9hUgIMn-fNIqg'; // api_secret_key; - axios.defaults.headers.common['x-account-id'] = '_XY7DXtc9MY'; // account_id; + let result = await download_file(api_base_url, api_endpoint, save_path); + event.sender.send('download_file_reply', result); - const url = api_endpoint; + // axios.defaults.baseURL = api_base_url; + // axios.defaults.headers.common['Access-Control-Allow-Origin'] = '*'; // app_config.access_control_allow_origin; + // axios.defaults.headers.common['content-type'] = 'application/json'; + // axios.defaults.headers.common['x-aether-api-key'] = 'dFP6J9DVj9hUgIMn-fNIqg'; // api_secret_key; + // axios.defaults.headers.common['x-account-id'] = '_XY7DXtc9MY'; // account_id; - axios({ - method: 'get', - url: url, - responseType: 'stream' /* responseType must be stream */ - }).then(function (response) { - response.data.pipe(fs.createWriteStream(save_path)); - }); + // const url = api_endpoint; + + // const writer = fs.createWriteStream(save_path); + + // await axios({ + // method: 'get', + // url: url, + // responseType: 'stream' /* responseType must be stream */ + // }).then(function (response) { + // console.log('Downloading...?'); + // // response.data.pipe(fs.createWriteStream(save_path)); + // // return true; + + // return new Promise((resolve, reject) => { + // response.data.pipe(writer); + // let error = null; + // writer.on('error', err => { + // console.log('Writer error!'); + // error = err; + // writer.close(); + // reject(err); + // }); + // writer.on('close', () => { + // console.log('Writer close!'); + // if (!error) { + // resolve(true); + // } + // //no need to call the reject here, as it will have been called in the + // //'error' stream; + // }); + // }); + // }) + // .catch(function (error) { + // if (error.response && error.response.status === 404) { + // return null; // Returning null since there were no results + // } + // console.log(`Response Status: ${error.response.status}; Status Text: ${error.response.statusText}`); + // // console.log(error); + // return false; // Returning false since something may have gone wrong. Also more in line with what the API returns. + // }); + + // event.sender.send('asynchronous-reply', true); }); +async function download_file(api_base_url, api_endpoint, save_path) { + return new Promise((resolve, reject) => { + + axios.defaults.baseURL = api_base_url; + axios.defaults.headers.common['Access-Control-Allow-Origin'] = '*'; // app_config.access_control_allow_origin; + axios.defaults.headers.common['content-type'] = 'application/json'; + axios.defaults.headers.common['x-aether-api-key'] = 'dFP6J9DVj9hUgIMn-fNIqg'; // api_secret_key; + axios.defaults.headers.common['x-account-id'] = '_XY7DXtc9MY'; // account_id; + + const url = api_endpoint; + + const writer = fs.createWriteStream(save_path); + + let result = axios({ + method: 'get', + url: url, + responseType: 'stream' /* responseType must be stream */ + }).then(function (response) { + console.log('Downloading...?'); + // response.data.pipe(fs.createWriteStream(save_path)); + // return true; + + return new Promise((resolve, reject) => { + response.data.pipe(writer); + let error = null; + writer.on('error', err => { + console.log('Writer error!'); + error = err; + writer.close(); + reject(err); + }); + writer.on('close', () => { + console.log('Writer close!'); + if (!error) { + resolve(true); + } + //no need to call the reject here, as it will have been called in the + //'error' stream; + }); + }); + }) + .catch(function (error) { + if (error.response && error.response.status === 404) { + return null; // Returning null since there were no results + } + console.log(`Response Status: ${error.response.status}; Status Text: ${error.response.statusText}`); + // console.log(error); + return false; // Returning false since something may have gone wrong. Also more in line with what the API returns. + }); + + resolve(result) + }) + } // ipcMain.on('open_local_file', (event, file_path, filename) => { // ipcMain.on('open_local_file', ({host_file_cache_path, hash, filename}) => { -ipcMain.on('open_local_file', (event, host_file_cache_path, hash, filename) => { - console.log(host_file_cache_path); +ipcMain.on('open_local_file', (event, host_file_cache_path, hash, host_file_temp_path, filename) => { console.log('ipcMain open local file: '+host_file_cache_path+' -> '+filename); let cache_file_path = path.join(process.cwd(), host_file_cache_path); @@ -134,23 +222,35 @@ ipcMain.on('open_local_file', (event, host_file_cache_path, hash, filename) => { let full_cache_file_path = path.join(cache_file_path, hash_filename); console.log(full_cache_file_path); - open_file_path = path.join(process.cwd(), 'temp/', filename); - console.log(open_file_path); + open_temp_file_path = path.join(process.cwd(), host_file_temp_path, filename); // 'temp/' + console.log(open_temp_file_path); - - if (fs.existsSync(open_file_path)) { - //console.log('File link already exists: '+open_file_path); + if (fs.existsSync(open_temp_file_path)) { + console.log('A file with the same name already exists in the local temp directory: '+open_temp_file_path); // NOTE: Should the file be checked to see if it has changed from the hashed cache version??? // NOTE: What if they made changes to the file locally in temp? The changed file would be used since a new copy is not being made. // NOTE: It might make sense for this to be a configurable option depending on the group. Some do not allow changes. This helps enforce that. - console.log('File copy already exists: '+open_file_path); - } else { - //console.log('Creating file link: '+open_file_path); - //fs.linkSync(full_cache_file_path, open_file_path); - console.log('Copying file to temp: '+open_file_path); - fs.copyFileSync(full_cache_file_path, open_file_path); } - shell.openPath(open_file_path); - //fs.open(open_file_path); + if (fs.existsSync(full_cache_file_path)) { + console.log('Hashed file cache exists: '+full_cache_file_path); + console.log('Copying file to temp: '+open_temp_file_path); + try { + fs.copyFileSync(full_cache_file_path, open_temp_file_path); + } catch (error) { + console.error(error); + return false; + } + + // console.log('Creating file link: '+open_temp_file_path); + // fs.linkSync(full_cache_file_path, open_temp_file_path); + } else { + return false; + } + + shell.openPath(open_temp_file_path); + //fs.open(open_temp_file_path); + // return true; + + event.sender.send('asynchronous-reply', true); });