Skip to content

Instantly share code, notes, and snippets.

@CookieCookson
Created May 9, 2017 08:51
Show Gist options
  • Save CookieCookson/7161ede4db4b5624dfd541cbe2ac58db to your computer and use it in GitHub Desktop.
Save CookieCookson/7161ede4db4b5624dfd541cbe2ac58db to your computer and use it in GitHub Desktop.
Persistent key/value storage for Cordova + Ionic V1
/**
* For this to work on devices, install the File plugin
* `cordova plugin add cordova-plugin-file --save`
* */
(function (angular) {
'use strict';
angular.module('elixel.fileStorage', ['ionic'])
.service('fileStorage', function($ionicPlatform, $q) {
// Use Persistent data storage for Desktop support
var fileSystemType = window.PERSISTENT || 1;
// Set the data storage maximum size needed for Desktop support (default: 10mb)
var size = 10 * (1024 * 1024);
var requestStorageQuota = function() {
var deferred = $q.defer();
if (navigator.webkitPersistentStorage) { // Webkit Implementation
navigator.webkitPersistentStorage.queryUsageAndQuota(
function(usedBytes, grantedBytes) {
deferred.resolve(grantedBytes);
},
function(error) {
deferred.reject(error);
}
);
} else if (navigator.persistentStorage) { // Non-webkit Implementation
navigator.persistentStorage.queryUsageAndQuota(
function(usedBytes, grantedBytes) {
deferred.resolve(grantedBytes);
},
function(error) {
deferred.reject(error);
}
);
} else { // Not supported
deferred.reject();
}
return deferred.promise;
};
var requestStorage = function() {
var deferred = $q.defer();
// Wait for device to be ready
$ionicPlatform.ready(function() {
if (window.cordova) { // Cordova Implementation
// Do not request access, Cordova already has permission
deferred.resolve();
} else if (navigator.webkitPersistentStorage) { // Webkit Implementation
navigator.webkitPersistentStorage.requestQuota(
size, function() {
deferred.resolve();
}, function(error) {
deferred.reject(error);
}
);
} else if (navigator.persistentStorage) { // Non-webkit Implementation
navigator.persistentStorage.requestQuota(
size, function() {
deferred.resolve();
}, function(error) {
deferred.reject(error);
}
);
} else { // Not supported
deferred.reject();
}
});
return deferred.promise;
};
var removeItemHandler = function(fs, key) {
var deferred = $q.defer();
fs.root.getFile(key + '.json', {}, function(fileEntry) {
fileEntry.remove(function() {
deferred.resolve(true);
}, function(error) {
deferred.reject(error);
});
}, function(error) {
deferred.reject(error);
});
return deferred.promise;
};
var removeItemFromFs = function(key) {
var deferred = $q.defer();
if (window.cordova) { // Cordova Implementation
window.resolveLocalFileSystemURL(
window.cordova.file.dataDirectory,
function(fs) {
removeItemHandler(fs.filesystem, key)
.then(function(fileStorageSuccess) {
deferred.resolve(fileStorageSuccess);
}, function(fileStorageError) {
deferred.reject(fileStorageError);
});
}
);
} else if (window.webkitRequestFileSystem) { // Webkit Implementation
window.webkitRequestFileSystem(
fileSystemType,
size,
function(fs) {
removeItemHandler(fs, key)
.then(function(fileStorageSuccess) {
deferred.resolve(fileStorageSuccess);
}, function(fileStorageError) {
deferred.reject(fileStorageError);
});
}
);
} else if (window.requestFileSystem) { // Non-webkit Implementation
window.requestFileSystem(
fileSystemType,
size,
function(fs) {
removeItemHandler(fs, key)
.then(function(fileStorageSuccess) {
deferred.resolve(fileStorageSuccess);
}, function(fileStorageError) {
deferred.reject(fileStorageError);
});
}
);
} else {
deferred.reject();
}
return deferred.promise;
};
/**
* Removes a value for a specified key (removes from localStorage and also from the file system)
*/
var removeItem = function(key) {
var deferred = $q.defer();
// Set value to localStorage
localStorage.removeItem(key);
// Wait for device to be ready
$ionicPlatform.ready(function() {
// Save value to fileStorage
removeItemFromFs(key)
.then(function(fileStorageSuccess) {
deferred.resolve(fileStorageSuccess);
}, function(fileStorageError) {
deferred.reject(fileStorageError);
});
});
return deferred.promise;
};
/**
* Sets the contents of a file on the device
*/
var setItemHandler = function(fs, key, value) {
var deferred = $q.defer();
fs.root.getFile(key + '.json', {
create: true
}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
var truncated = false;
fileWriter.onwriteend = function() {
if (!truncated) {
truncated = true;
this.truncate(this.position);
deferred.resolve(true);
}
};
fileWriter.onerror = function(error) {
deferred.reject(error);
};
var obj = {};
obj[key] = value;
var blob = new Blob([JSON.stringify(obj)], {
type: 'application/json'
});
fileWriter.write(blob);
}, function(error) {
deferred.reject(error);
});
}, function(error) {
deferred.reject(error);
});
return deferred.promise;
};
/**
* Redirects the save call depending on the browser support
*/
var setItemToFs = function(key, value) {
var deferred = $q.defer();
if (window.cordova) { // Cordova Implementation
window.resolveLocalFileSystemURL(
window.cordova.file.dataDirectory,
function(fs) {
setItemHandler(fs.filesystem, key, value)
.then(function(success) {
deferred.resolve(success);
}, function(error) {
deferred.reject(error);
});
}
);
} else if (window.webkitRequestFileSystem) { // Webkit Implementation
window.webkitRequestFileSystem(
fileSystemType,
size,
function(fs) {
setItemHandler(fs, key, value)
.then(function(success) {
deferred.resolve(success);
}, function(error) {
deferred.reject(error);
});
}
);
} else if (window.requestFileSystem) { // Non-webkit Implementation
window.requestFileSystem(
fileSystemType,
size,
function(fs) {
setItemHandler(fs, key, value)
.then(function(success) {
deferred.resolve(success);
}, function(error) {
deferred.reject(error);
});
}
);
} else { // No implementation supported!
deferred.reject();
}
return deferred.promise;
};
/**
* Sets a value for a specified key (sets localStorage and also as a file)
*/
var setItem = function(key, value) {
var deferred = $q.defer();
// Set value to localStorage
localStorage.setItem(key, value);
// Wait for device to be ready
$ionicPlatform.ready(function() {
// Save value to fileStorage
setItemToFs(key, value)
.then(function(fileStorageSuccess) {
deferred.resolve(fileStorageSuccess);
}, function(fileStorageError) {
deferred.reject(fileStorageError);
});
});
return deferred.promise;
};
/**
* Returns the contents of a file on the device
*/
var getItemHandler = function(fs, key) {
var deferred = $q.defer();
fs.root.getFile(key + '.json', {}, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onloadend = function(fileContents) {
deferred.resolve(fileContents ? JSON.parse(this.result)[key] : null);
};
reader.readAsText(file);
}, function(error) {
if (error.code === 1) {
deferred.resolve(null);
} else {
deferred.reject(error);
}
});
}, function(error) {
if (error.code === 8 || error.code === 1) { // code 1 == file not found on device
deferred.resolve(null);
} else {
deferred.reject(error);
}
});
return deferred.promise;
};
/**
* Redirects the fileStorage call depending on the browser support
*/
var getItemFromFs = function(key) {
var deferred = $q.defer();
if (window.cordova) { // Cordova Implementation
window.resolveLocalFileSystemURL(
window.cordova.file.dataDirectory,
function(fs) {
getItemHandler(fs.filesystem, key)
.then(function(value) {
deferred.resolve(value);
}, function(error) {
deferred.reject(error);
});
}
);
} else if (window.webkitRequestFileSystem) { // Webkit Implementation
window.webkitRequestFileSystem(
fileSystemType,
size,
function(fs) {
getItemHandler(fs, key)
.then(function(value) {
deferred.resolve(value);
}, function(error) {
deferred.reject(error);
});
}
);
} else if (window.requestFileSystem) { // Non-webkit Implementation
window.requestFileSystem(
fileSystemType,
size,
function(fs) {
getItemHandler(fs, key)
.then(function(value) {
deferred.resolve(value);
}, function(error) {
deferred.reject(error);
});
}
);
} else { // No implementation supported!
deferred.resolve(null);
}
return deferred.promise;
};
/**
* Returns a value for specified key (checks localStorage first then the device)
*/
var getItem = function(key) {
var deferred = $q.defer();
// Get value from localStorage
var localStorageValue = localStorage.getItem(key);
// Check if the key is present in localStorage
if (localStorageValue !== null) {
// Resolve localStorage persisted value
deferred.resolve(localStorageValue);
} else { // Key is not present, it either does not exist or has been cleared
// Wait for device to be ready
$ionicPlatform.ready(function() {
// Return if key is in fileStorage
getItemFromFs(key)
.then(function(fileStorageValue) {
deferred.resolve(fileStorageValue);
}, function(fileStorageError) {
deferred.reject(fileStorageError);
});
});
}
return deferred.promise;
};
// Request storage permissions for desktop environment
requestStorage();
/**
* Return all public functions
*/
return {
getItem: getItem,
setItem: setItem,
removeItem: removeItem,
requestStorageQuota: requestStorageQuota
};
});
})(window.angular);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment