diff --git a/package.cordovabuild.json b/package.cordovabuild.json index 23d2d38ad..cf47bbd4e 100644 --- a/package.cordovabuild.json +++ b/package.cordovabuild.json @@ -67,7 +67,6 @@ "ANDROID_HOST": " ", "ANDROID_PATHPREFIX": "/" }, - "cordova-plugin-email-composer": {}, "cordova-plugin-x-socialsharing": { "PHOTO_LIBRARY_ADD_USAGE_DESCRIPTION": "This app requires photo library access to share photos on social media.", "PHOTO_LIBRARY_USAGE_DESCRIPTION": "This app requires photo library access to share photos on social media." @@ -128,7 +127,6 @@ "cordova-plugin-em-settings": "git+https://github.com/e-mission/cordova-connection-settings.git#v1.2.3", "cordova-plugin-em-unifiedlogger": "git+https://github.com/e-mission/cordova-unified-logger.git#v1.3.6", "cordova-plugin-em-usercache": "git+https://github.com/e-mission/cordova-usercache.git#v1.1.9", - "cordova-plugin-email-composer": "git+https://github.com/katzer/cordova-plugin-email-composer.git#0.10.1", "cordova-plugin-file": "8.0.0", "cordova-plugin-inappbrowser": "5.0.0", "cordova-plugin-ionic-keyboard": "2.2.0", diff --git a/www/i18n/en.json b/www/i18n/en.json index dfccf1f5e..7347f8e46 100644 --- a/www/i18n/en.json +++ b/www/i18n/en.json @@ -23,7 +23,7 @@ "force-sync": "Force sync", "share": "Share", "download-json-dump": "Download json dump", - "email-log": "Email log", + "share-log": "Share log", "upload-log": "Upload log", "view-privacy": "View Privacy Policy", "user-data": "User data", @@ -278,16 +278,14 @@ "reading-unprocessed-data": "Reading unprocessed data..." }, - "email-service": { - "email-account-not-configured": "Email account is not configured, cannot send email", - "email-account-mail-app": "You must have the mail app on your phone configured with an email address. Otherwise, this won't work", - "going-to-email": "Going to email database from {{parentDir}}", - "email-log": { + "shareFile-service": { + "send-to": "Please send this file to openpath@nrel.gov, or another OpenPATH team member.", + "send-log": { "subject-logs": "emission logs", "body-please-fill-in-what-is-wrong": "please fill in what is wrong" }, "no-email-address-configured": "No email address configured.", - "email-data": { + "send-data": { "subject-data-dump-from-to": "Data dump from {{start}} to {{end}}", "body-data-consists-of-list-of-entries": "Data consists of a list of entries.\nEntry formats are at https://github.com/e-mission/e-mission-server/tree/master/emission/core/wrapper \nData can be loaded locally using instructions at https://github.com/e-mission/e-mission-server#loading-test-data \n and can be manipulated using the example at https://github.com/e-mission/e-mission-server/blob/master/Timeseries_Sample.ipynb" } diff --git a/www/js/control/LogPage.tsx b/www/js/control/LogPage.tsx index 96ef290b3..0d7a362c0 100644 --- a/www/js/control/LogPage.tsx +++ b/www/js/control/LogPage.tsx @@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next'; import { FlashList } from '@shopify/flash-list'; import { DateTime } from 'luxon'; import { AlertManager } from '../components/AlertBar'; -import { sendEmail } from './emailService'; +import { sendLocalDBFile } from '../services/shareLocalDBFile'; import { displayError, logDebug } from '../plugin/logger'; import NavBar from '../components/NavBar'; @@ -93,7 +93,7 @@ const LogPage = ({ pageVis, setPageVis }) => { } function emailLog() { - sendEmail('loggerDB'); + sendLocalDBFile('loggerDB'); } const separator = () => ; diff --git a/www/js/control/ProfileSettings.tsx b/www/js/control/ProfileSettings.tsx index 794a37bcb..264ba8ba0 100644 --- a/www/js/control/ProfileSettings.tsx +++ b/www/js/control/ProfileSettings.tsx @@ -13,7 +13,7 @@ import useAppConfig from '../useAppConfig'; import { AlertManager } from '../components/AlertBar'; import DataDatePicker from './DataDatePicker'; import PrivacyPolicyModal from './PrivacyPolicyModal'; -import { sendEmail } from './emailService'; +import { sendLocalDBFile } from '../services/shareLocalDBFile'; import { uploadFile } from './uploadService'; import ActionMenu from '../components/ActionMenu'; import SensedPage from './SensedPage'; @@ -448,9 +448,9 @@ const ProfileSettings = () => { action={() => setDateDumpVis(true)}> {logUploadSection} sendEmail('loggerDB')}> + action={() => sendLocalDBFile('loggerDB')}> { @@ -60,7 +60,7 @@ const SensedPage = ({ pageVis, setPageVis }) => { updateEntries()} /> - sendEmail('userCacheDB')} /> + sendLocalDBFile('userCacheDB')} /> { - return new Promise((resolve, reject) => { - window['cordova'].plugins['email'].hasAccount((hasAct) => { - resolve(hasAct); - }); - }); -} - -export async function sendEmail(database: string) { - let parentDir = 'unknown'; - - if (window['cordova'].platformId == 'ios' && !(await hasAccount())) { - alert(i18next.t('email-service.email-account-not-configured')); - return; - } - - if (window['cordova'].platformId == 'android') { - parentDir = 'app://databases'; - } - - if (window['cordova'].platformId == 'ios') { - alert(i18next.t('email-service.email-account-mail-app')); - logDebug(window['cordova'].file.dataDirectory); - parentDir = window['cordova'].file.dataDirectory + '../LocalDatabase'; - } - - if (parentDir === 'unknown') { - alert('parentDir unexpectedly = ' + parentDir + '!'); - } - - logInfo('Going to email ' + database); - parentDir = parentDir + '/' + database; - - alert(i18next.t('email-service.going-to-email', { parentDir: parentDir })); - - let emailConfig = `k.shankari@nrel.gov`; - - let emailData = { - to: emailConfig, - attachments: [parentDir], - subject: i18next.t('email-service.email-log.subject-logs'), - body: i18next.t('email-service.email-log.body-please-fill-in-what-is-wrong'), - }; - - window['cordova'].plugins['email'].open(emailData, () => { - logWarn(`Email app closed while sending, - emailData = ${JSON.stringify(emailData)}`); - }); -} diff --git a/www/js/services/controlHelper.ts b/www/js/services/controlHelper.ts index 1a9016557..da2e60ed7 100644 --- a/www/js/services/controlHelper.ts +++ b/www/js/services/controlHelper.ts @@ -54,9 +54,9 @@ export function getMyDataHelpers(fileName: string, startTimeString: string, endT const shareObj = { files: [attachFile], message: i18next.t( - 'email-service.email-data.body-data-consists-of-list-of-entries', + 'shareFile-service.send-data.body-data-consists-of-list-of-entries', ), - subject: i18next.t('email-service.email-data.subject-data-dump-from-to', { + subject: i18next.t('shareFile-service.send-data.subject-data-dump-from-to', { start: startTimeString, end: endTimeString, }), diff --git a/www/js/services/shareLocalDBFile.ts b/www/js/services/shareLocalDBFile.ts new file mode 100644 index 000000000..484604371 --- /dev/null +++ b/www/js/services/shareLocalDBFile.ts @@ -0,0 +1,121 @@ +import i18next from 'i18next'; +import { displayError, displayErrorMsg, logDebug, logWarn } from '../plugin/logger'; + +function localDBHelpers(fileName: string, fileExtension: string = '.txt') { + async function localCopyFile() { + return new Promise((resolve, reject) => { + let pathToFile, parentDirectory; + if (window['cordova'].platformId == 'android') { + // parentDirectory: file:///data/user/0/edu.berkeley.eecs.emission/files/ + parentDirectory = window['cordova'].file.dataDirectory.replace('files', 'databases'); + // pathToFile: /data/user/0/edu.berkeley.eecs.emission/files/ + pathToFile = parentDirectory.replace('file://', '') + fileName; + } else if (window['cordova'].platformId == 'ios') { + // parentDirectory: file:///var/mobile/Containers/Data/Application/<32-hex-digit-id>/Library/NoCloud/../ + parentDirectory = window['cordova'].file.dataDirectory + '../'; + pathToFile = 'LocalDatabase/' + fileName; + } else { + displayErrorMsg('Error: Unknown OS!'); + throw new Error('Error: Unknown OS!'); + } + + window['resolveLocalFileSystemURL'](parentDirectory, (fs) => { + // On iOS, pass in relative path to getFile https://github.com/e-mission/e-mission-phone/pull/1160#issuecomment-2192112472 + // On Android, pass in absolute path to getFile https://github.com/e-mission/e-mission-phone/pull/1160#issuecomment-2204297874 + fs.filesystem.root.getFile(pathToFile, { create: false, exclusive: false }, (fileEntry) => { + // logDebug(`fileEntry ${fileEntry.nativeURL} is file? ${fileEntry.isFile.toString()}`); + logDebug(`fileEntry is: ${JSON.stringify(fileEntry, null, 2)}`); + window['resolveLocalFileSystemURL'](window['cordova'].file.cacheDirectory, (copyDir) => { + logDebug(`DirectoryEntry is: ${JSON.stringify(copyDir.filesystem.root, null, 2)}`); + + fileEntry.copyTo( + copyDir.filesystem.root, + fileName + fileExtension, + (res) => { + logDebug(`Res: ${res}`); + resolve(); + }, + (rej) => { + displayErrorMsg(`Rej: ${JSON.stringify(rej, null, 2)}`); + reject(); + }, + ); + }); + }); + }); + }); + } + + function localShareFile() { + return new Promise((resolve, reject) => { + window['resolveLocalFileSystemURL'](window['cordova'].file.cacheDirectory, (fs) => { + fs.filesystem.root.getFile( + fileName + fileExtension, + null, + (fileEntry) => { + const shareObj = { + files: [fileEntry.nativeURL], + message: i18next.t('shareFile-service.send-log.body-please-fill-in-what-is-wrong'), + subject: i18next.t('shareFile-service.send-log.subject-logs'), + }; + window['plugins'].socialsharing.shareWithOptions( + shareObj, + (result) => { + logDebug(`Share Completed? ${result.completed}`); // On Android, most likely returns false + logDebug(`Shared to app: ${result.app}`); + resolve(); + }, + (error) => { + displayError(error, `Sharing failed with error`); + }, + ); + }, + (error) => { + displayError(error, 'Error while sharing logs'); + reject(error); + }, + ); + }); + }); + } + + function localClearTmpFile() { + return new Promise((resolve, reject) => { + window['resolveLocalFileSystemURL'](window['cordova'].file.cacheDirectory, (fs) => { + fs.filesystem.root.getFile(fileName + fileExtension, null, (fileEntry) => { + fileEntry.remove( + () => { + logDebug(`Successfully cleaned up file ${fileName}`); + resolve(); + }, + (err) => { + displayError(err, `Error deleting ${fileName}`); + reject(err); + }, + ); + }); + }); + }); + } + + return { + copyFile: localCopyFile, + shareData: localShareFile, + clearTmpFile: localClearTmpFile, + }; +} +export async function sendLocalDBFile(database: string) { + alert(i18next.t('shareFile-service.send-to')); + + const dataMethods = localDBHelpers(database); + dataMethods + .copyFile() + .then(dataMethods.shareData) + .then(dataMethods.clearTmpFile) + .then(() => { + logDebug(`File Shared!`); + }) + .catch((err) => { + displayError(err); + }); +}