diff --git a/src/fileUtils.js b/src/fileUtils.js index db98ed2..f997da6 100644 --- a/src/fileUtils.js +++ b/src/fileUtils.js @@ -13,5 +13,31 @@ export default { // Clean up URL.revokeObjectURL(url) downloader.remove() + }, + + /** + * Note: if user press Cancel in file choosing dialog + * it will be an unsettled promise. But it's grabbed by + * the garbage collector (tested with FinalizationRegistry). + */ + importFile () { + return new Promise((resolve, reject) => { + const uploader = document.createElement('input') + + uploader.id = 'file-uploader' + uploader.type = 'file' + uploader.accept = '.json' + + uploader.addEventListener('change', () => { + const file = uploader.files[0] + const reader = new FileReader() + reader.onload = (e) => { + resolve(e.target.result) + } + reader.readAsText(file) + }) + + uploader.click() + }) } } diff --git a/src/storedQueries.js b/src/storedQueries.js index 65e0c9f..e8f9b34 100644 --- a/src/storedQueries.js +++ b/src/storedQueries.js @@ -1,4 +1,5 @@ import { nanoid } from 'nanoid' +import fu from '@/fileUtils' export default { getStoredQueries () { @@ -65,54 +66,29 @@ export default { return JSON.stringify(preparedData, null, 4) }, - /** - * It calls onSuccess with imported queries as argument when - * file read. We can't use Promises here because we can't - * catch the Cancel event when a user choose a file. - */ - importQueries (onSuccess) { - let uploader = document.getElementById('file-uploader') - - // Create uploader if it doesn't exists - if (!uploader) { - uploader = document.createElement('input') - uploader.id = 'file-uploader' - uploader.type = 'file' - uploader.accept = '.json' - uploader.hidden = true - - uploader.addEventListener('change', () => { - const file = uploader.files[0] - const reader = new FileReader() - reader.onload = (e) => { - // Parse data - let importedQueries = JSON.parse(e.target.result) - - // Turn data into array if they are not - if (!Array.isArray(importedQueries)) { - importedQueries = [importedQueries] - } - - // Generate new ids if they are the same as existing queries - importedQueries.forEach(query => { - const allQueriesIds = this.getStoredQueries().map(query => query.id) - if (new Set(allQueriesIds).has(query.id)) { - query.id = nanoid() - } - }) - - // Clear uploader - uploader.value = null - - // Call callback - onSuccess(importedQueries) - } - reader.readAsText(file) - }) - - document.body.append(uploader) + deserialiseQueries (str) { + let queryList = JSON.parse(str) + // Turn data into array if they are not + if (!Array.isArray(queryList)) { + queryList = [queryList] } - uploader.click() + + // Generate new ids if they are the same as existing queries + queryList.forEach(query => { + const allQueriesIds = this.getStoredQueries().map(query => query.id) + if (allQueriesIds.includes(query.id)) { + query.id = nanoid() + } + }) + + return queryList + }, + + importQueries () { + return fu.importFile() + .then(data => { + return this.deserialiseQueries(data) + }) }, readPredefinedQueries () { diff --git a/src/views/MyQueries.vue b/src/views/MyQueries.vue index 5e7ba32..54fab7e 100644 --- a/src/views/MyQueries.vue +++ b/src/views/MyQueries.vue @@ -368,18 +368,18 @@ export default { this.exportToFile(queryList, 'My sqlitevis queries.json') }, importQueries () { - const onSuccess = (importedQueries) => { - if (this.selectAll) { - importedQueries.forEach(query => { - this.selectedQueriesIds.add(query.id) - }) - this.selectedQueriesCount = this.selectedQueriesIds.size - } + storedQueries.importQueries() + .then(importedQueries => { + if (this.selectAll) { + importedQueries.forEach(query => { + this.selectedQueriesIds.add(query.id) + }) + this.selectedQueriesCount = this.selectedQueriesIds.size + } - this.queries = this.queries.concat(importedQueries) - storedQueries.updateStorage(this.queries) - } - storedQueries.importQueries(onSuccess) + this.queries = this.queries.concat(importedQueries) + storedQueries.updateStorage(this.queries) + }) }, toggleSelectAll (checked) { this.selectAll = checked