From 31ac019f2805231a37423cc4457400105fd4bb26 Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Fri, 14 Feb 2025 15:53:54 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix=20"share=20log"=20error=20du?= =?UTF-8?q?e=20to=20leftover=20loggerDB=20tmp=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/e-mission/e-mission-docs/issues/1110 After sharing the tmp DB file, we try to clear it, but if this operation fails or the app exits before we get to this, for any reason, all subsequent attempts to share the DB file would fail with error 12 (PATH_EXISTS_ERR) A simple solution is to attempt to clear the tmp file before *and* after sharing. I also changed this to async/await syntax to make it clearer what is happening. Testing done: I ran a dev build of emission on an Android test phone. From profile I clicked Share log and saw the "tmp file did not exist, that is fine..." log The share menu came up but before dismissing it I went into app settings and Force Quit the app. This caused a leftover tmp file that was not cleared. (I never saw "Successfully cleaned up file loggerDB" in the console) Then I launched the app again and repeated the same steps. This time I saw "Successfully cleaned up file..." in the console. The user-visible behavior was the same (share menu popped up). After allowing the share menu to dismiss, I saw "Successfully cleaned up file loggerDB" again --- www/js/services/shareLocalDBFile.ts | 194 ++++++++++++++-------------- 1 file changed, 98 insertions(+), 96 deletions(-) diff --git a/www/js/services/shareLocalDBFile.ts b/www/js/services/shareLocalDBFile.ts index 484604371..f91a25d5c 100644 --- a/www/js/services/shareLocalDBFile.ts +++ b/www/js/services/shareLocalDBFile.ts @@ -1,88 +1,91 @@ import i18next from 'i18next'; -import { displayError, displayErrorMsg, logDebug, logWarn } from '../plugin/logger'; +import { displayError, displayErrorMsg, logDebug } 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!'); - } +function localCopyFile(fileName: string, fileExtension: string = '.txt') { + 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)}`); + 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(); - }, - ); - }); + 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 localShareFile(fileName: string, fileExtension: string = '.txt') { + 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) => { +function localClearTmpFile(fileName: string, fileExtension: string = '.txt') { + return new Promise((resolve, reject) => { + window['resolveLocalFileSystemURL'](window['cordova'].file.cacheDirectory, (fs) => { + fs.filesystem.root.getFile( + fileName + fileExtension, + null, + (fileEntry) => { + logDebug(`got fileEntry: ${JSON.stringify(fileEntry, null, 2)}`); fileEntry.remove( () => { logDebug(`Successfully cleaned up file ${fileName}`); @@ -93,29 +96,28 @@ function localDBHelpers(fileName: string, fileExtension: string = '.txt') { reject(err); }, ); - }); - }); + }, + (getFileError) => { + logDebug(`tmp file did not exist, that is fine: ${JSON.stringify(getFileError)}`); + resolve(); + }, + ); }); - } - - return { - copyFile: localCopyFile, - shareData: localShareFile, - clearTmpFile: localClearTmpFile, - }; + }); } -export async function sendLocalDBFile(database: string) { + +export async function sendLocalDBFile(dbFileName: 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); - }); + try { + // in case there is a leftover tmp file, clear it before sharing + await localClearTmpFile(dbFileName); + await localCopyFile(dbFileName); + await localShareFile(dbFileName); + // clear the tmp file after sharing + await localClearTmpFile(dbFileName); + logDebug(`File Shared!`); + } catch (err) { + displayError(err); + } }