Skip to content

Commit

Permalink
Import custom localforage which maps to cordova file api
Browse files Browse the repository at this point in the history
  • Loading branch information
MarmadileManteater committed Feb 2, 2024
1 parent 636f570 commit 561bd55
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 2 deletions.
5 changes: 3 additions & 2 deletions _scripts/webpack.cordova.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ const config = {
}),
new webpack.ProvidePlugin({
process: 'process/browser',
Buffer: ['buffer', 'Buffer'],
Buffer: ['buffer', 'Buffer']
}),
new HtmlWebpackPlugin({
excludeChunks: ['processTaskWorker'],
Expand All @@ -154,7 +154,8 @@ const config = {
// video.js's mpd-parser uses @xmldom/xmldom so that it can support both node and web browsers
// As FreeTube only runs in electron and web browsers, we can use the native DOMParser class, instead of the "polyfill"
// https://caniuse.com/mdn-api_domparser
'@xmldom/xmldom$': path.resolve(__dirname, '_domParser.js')
'@xmldom/xmldom$': path.resolve(__dirname, '_domParser.js'),
'localforage': path.resolve(__dirname, "../src/cordova/localforage.js")
},
fallback: {
'fs/promises': path.resolve(__dirname, '_empty.js'),
Expand Down
20 changes: 20 additions & 0 deletions src/cordova/localforage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import localforage from '../../node_modules/localforage/dist/localforage'
import { requestDirectory, readFromFile, writeToFile } from '../renderer/helpers/cordova'

export function createInstance(kwargs) {
const instance = localforage.createInstance(kwargs)
return {
async getItem(key) {
const fs = await requestDirectory()
const data = await readFromFile(fs, key)
// if the data is empty, fallback to localstorage
if (data === '') return instance.getItem(key)
// if not, return the data
return data
},
async setItem(key, value) {
const fs = await requestDirectory()
await writeToFile(fs, key, value)
}
}
}
126 changes: 126 additions & 0 deletions src/renderer/helpers/cordova.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import cordova from 'cordova'

/**
* @typedef FileOptions
* @property {boolean} create
* @property {boolean} exclusive
*/

/**
* @typedef Writer
* @property {Function} onerror
* @property {Function} write
*/

/**
* @callback CreateWriterCallback
* @param {Writer} writer
* @returns {void}
*/

/**
* @callback CreateWriter
* @param {CreateWriterCallback} callback
* @returns {void}
*/

/**
* @callback GetBlobCallback
* @param {Blob} blob
* @returns {void}
*/

/**
* @callback GetBlob
* @param {GetBlobCallback} callback
*/

/**
* @typedef FileReference
* @property {CreateWriter} createWriter
* @property {GetBlob} file
*/

/**
* @callback GetFileCallback
* @param {FileReference} file
*/

/**
* @callback GetFile
* @param {string} patch
* @param {FileOptions} options
* @param {GetFileCallback} callback
* @returns {void}
*/

/**
* @typedef FileSystemHook
* @property {GetFile} getFile
*/

/**
*
* @param {string} directory this *must* be one of the accepted cordova file keys "cordova.file.*""
* @returns {Promise<FileSystemHook>} a filesystem hook that starts in the given directory
*/
export function requestDirectory(directory = cordova.file.externalApplicationStorageDirectory) {
return new Promise((resolve, _reject) => {
window.requestFileSystem(window.LocalFileSystem.PERSISTENT, 10000, function (_) {
window.resolveLocalFileSystemURL(directory, resolve)
})
})
}

/**
*
* @param {FileSystemHook} fsHook
* @param {string} path
* @param {string} content
* @param {FileOptions} options
* @returns {Promise<void>}
*/
export function writeToFile(fsHook, path, content, options = { create: true, exclusive: false }) {
return new Promise((resolve, reject) => {
fsHook.getFile(path, options, (file) => {
file.createWriter((writer) => {
writer.onerror = reject
writer.write(content)
resolve()
})
})
})
}

/**
*
* @param {FileSystemHook} fsHook
* @param {string} path
* @param {string} content
* @param {FileOptions} options
* @returns {Promise<string>}
*/
export function readFromFile(fsHook, path) {
return new Promise((resolve, reject) => {
fsHook.getFile(path, { create: true, exclusive: false }, (fileEntry) => {
fileEntry.file((file) => {
const reader = new FileReader()
reader.onloadend = () => resolve(reader.result)
reader.onerror = (e) => reject(e)
reader.readAsText(file)
})
})
})
}

export function removeFile(fsHook, path) {
return new Promise((resolve, reject) => {
fsHook.remove(() => {
resolve()
}, (error) => {
reject(error)
}, () => {
reject(new Error('File does not exist'))
})
})
}

0 comments on commit 561bd55

Please sign in to comment.