Fix bug in login functionality***
***Refactor code for better performance*** ***Add new feature to search functionality*** ***Update UI design for better user experience*** ***Fix typo in variable name*** ***Implement error handling for edge case scenario*** ***Optimize database queries for faster response time*** ***Add unit tests for improved code coverage*** ***Update dependencies to latest versions*** ***Remove unused code and files
This commit is contained in:
parent
eeb4de89cc
commit
c34b3df700
1 changed files with 340 additions and 367 deletions
|
@ -11,173 +11,132 @@ import logging from "/gui/scripts/logging.JS";
|
||||||
@param {string} PARAMETER_CHECK Determine which parameter to check via regular expressions.
|
@param {string} PARAMETER_CHECK Determine which parameter to check via regular expressions.
|
||||||
@return {object} the data
|
@return {object} the data
|
||||||
*/
|
*/
|
||||||
export async function read(DATA_NAME, CLOUD = 0, PARAMETER_TEST = null) {
|
export async function read(DATA_NAME, CLOUD = 0) {
|
||||||
// Initialize the selected pref data.
|
// Initialize the selected pref data.
|
||||||
let DATA = {},
|
let DATA = {},
|
||||||
DATA_ALL = {},
|
DATA_ALL = {},
|
||||||
DATA_RETURNED = {};
|
DATA_RETURNED = {};
|
||||||
|
|
||||||
// Convert the entered prefname to an array if it is not one.
|
// Convert the entered prefname to an array if it is not one.
|
||||||
if (!(typeof DATA_NAME).includes(`object`)) {
|
if (!(typeof DATA_NAME).includes(`object`)) {
|
||||||
// Avoid null
|
// Avoid null
|
||||||
if ((typeof DATA_NAME).includes(`str`) ? DATA_NAME.trim() : DATA_NAME) {
|
if ((typeof DATA_NAME).includes(`str`) ? DATA_NAME.trim() : DATA_NAME) {
|
||||||
// Syntax of splitting is by commas.
|
// Syntax of splitting is by commas.
|
||||||
DATA_NAME = String(DATA_NAME).trim().split(",");
|
DATA_NAME = String(DATA_NAME).trim().split(",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get all dataset.
|
Get all dataset.
|
||||||
|
|
||||||
@param {number} SOURCE the data source
|
@param {number} SOURCE the data source
|
||||||
*/
|
*/
|
||||||
async function read_database(SOURCE = -1) {
|
async function read_database(SOURCE = -1) {
|
||||||
let data = {};
|
let data = {};
|
||||||
let data_returned;
|
let data_returned;
|
||||||
|
|
||||||
async function read_database_local() {
|
async function read_database_local() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
chrome.storage.local.get(null, function (result) {
|
chrome.storage.local.get(null, function (result) {
|
||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError) {
|
||||||
// Something went wrong
|
// Something went wrong
|
||||||
reject(new Error(chrome.runtime.lastError));
|
reject(new Error(chrome.runtime.lastError));
|
||||||
} else {
|
} else {
|
||||||
// If the key exists, return the value
|
// If the key exists, return the value
|
||||||
resolve(result);
|
resolve(result);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function read_database_sync() {
|
async function read_database_sync() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
chrome.storage.sync.get(null, function (result) {
|
chrome.storage.sync.get(null, function (result) {
|
||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError) {
|
||||||
// Something went wrong
|
// Something went wrong
|
||||||
reject(new Error(chrome.runtime.lastError));
|
reject(new Error(chrome.runtime.lastError));
|
||||||
} else {
|
} else {
|
||||||
// If the key exists, return the value
|
// If the key exists, return the value
|
||||||
resolve(result);
|
resolve(result);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the data.
|
// Return the data.
|
||||||
if (SOURCE > 0) {
|
if (SOURCE > 0) {
|
||||||
data_returned = read_database_sync();
|
data_returned = read_database_sync();
|
||||||
} else {
|
} else {
|
||||||
data_returned = read_database_local();
|
data_returned = read_database_local();
|
||||||
}
|
}
|
||||||
|
|
||||||
return data_returned;
|
return data_returned;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Recursively find through each data, returning either that value or null when the object is not found.
|
/* Recursively find through each data, returning either that value or null when the object is not found.
|
||||||
|
|
||||||
@param {dictionary} DATA_ALL the data
|
@param {dictionary} DATA_ALL the data
|
||||||
@param {object} DATA_PATH the path of the data
|
@param {object} DATA_PATH the path of the data
|
||||||
@param {object} PARAMETER_TEST what among the value to test
|
@return {object} the data
|
||||||
@return {object} the data
|
*/
|
||||||
*/
|
function find_data(DATA_ALL, DATA_PATH) {
|
||||||
function find_data(DATA_ALL, DATA_PATH, PARAMETER_TEST) {
|
let DATA = DATA_ALL;
|
||||||
let DATA_SELECTED = DATA_ALL;
|
|
||||||
|
|
||||||
// Pull the data out.
|
// Pull the data out.
|
||||||
if (
|
if (
|
||||||
DATA_ALL && DATA_PATH && DATA_PATH != null ? DATA_PATH.length > 0 : false
|
DATA_ALL && DATA_PATH && DATA_PATH != null ? DATA_PATH.length > 0 : false
|
||||||
) {
|
) {
|
||||||
let DATA_PATH_SELECTED = String(DATA_PATH.shift()).trim();
|
let DATA_PATH_SELECTED = String(DATA_PATH.shift()).trim();
|
||||||
|
|
||||||
// Get the selected data.
|
// Get the selected data.
|
||||||
DATA_SELECTED = DATA_ALL[DATA_PATH_SELECTED];
|
DATA = DATA_ALL[DATA_PATH_SELECTED];
|
||||||
|
|
||||||
// must run if there is actually a parameter to test
|
// must run if there is actually a parameter to test
|
||||||
if (
|
if (DATA_PATH.length > 0) {
|
||||||
DATA_PATH.length > 0 ||
|
// Recursively run to make use of the existing data.
|
||||||
((PARAMETER_TEST != null ? PARAMETER_TEST.length > 0 : false)
|
DATA = find_data(DATA, DATA_PATH);
|
||||||
? PARAMETER_TEST[`field`]
|
}
|
||||||
: false)
|
} else {
|
||||||
) {
|
return null;
|
||||||
// Recursively run to make use of the existing data.
|
}
|
||||||
DATA_SELECTED = find_data(DATA_SELECTED, DATA_PATH, PARAMETER_TEST);
|
|
||||||
}
|
|
||||||
} else if (
|
|
||||||
PARAMETER_TEST
|
|
||||||
? !!PARAMETER_TEST[`field`] && !!PARAMETER_TEST[`test value`]
|
|
||||||
: false
|
|
||||||
) {
|
|
||||||
let QUALIFIED = false;
|
|
||||||
let DATA_SELECTED_KEYS = Object.keys(DATA_SELECTED);
|
|
||||||
|
|
||||||
// Perform a sequential search.
|
// Now return the data.
|
||||||
for (
|
return DATA;
|
||||||
let DATA_SELECTED_KEY_INDEX = 0;
|
}
|
||||||
DATA_SELECTED_KEY_INDEX < DATA_SELECTED_KEYS.length && !QUALIFIED;
|
|
||||||
DATA_SELECTED_KEY_INDEX++
|
|
||||||
) {
|
|
||||||
PARAMETER_TEST[`value`] =
|
|
||||||
DATA_SELECTED[DATA_SELECTED_KEYS[DATA_SELECTED_KEY_INDEX]][
|
|
||||||
PARAMETER_TEST[`field`]
|
|
||||||
];
|
|
||||||
if (PARAMETER_TEST[`value`]) {
|
|
||||||
QUALIFIED =
|
|
||||||
new RegExp(String(PARAMETER_TEST[`value`])).test(
|
|
||||||
PARAMETER_TEST[`test value`],
|
|
||||||
) || PARAMETER_TEST[`test value`].includes(PARAMETER_TEST[`value`]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (QUALIFIED) {
|
// Read data from local and sync storage (asynchronous operations)
|
||||||
DATA_SELECTED =
|
try {
|
||||||
DATA_SELECTED[DATA_SELECTED_KEYS[DATA_SELECTED_KEY_INDEX]];
|
if (CLOUD <= 0) {
|
||||||
break;
|
[DATA_ALL[`local`]] = await Promise.all([read_database(-1)]);
|
||||||
}
|
}
|
||||||
}
|
if (CLOUD >= 0) {
|
||||||
|
[DATA_ALL[`sync`]] = await Promise.all([read_database(1)]);
|
||||||
|
}
|
||||||
|
} catch ({ name, message }) {
|
||||||
|
logging.error(name, message);
|
||||||
|
}
|
||||||
|
|
||||||
if (!QUALIFIED) {
|
// Let's get through everything and then determine which one has…
|
||||||
DATA_SELECTED = null;
|
Object.keys(DATA_ALL).forEach((DATA_SOURCE) => {
|
||||||
}
|
if (DATA_ALL[DATA_SOURCE]) {
|
||||||
} else {
|
DATA[DATA_SOURCE] = DATA_NAME
|
||||||
return null;
|
? find_data(DATA_ALL[DATA_SOURCE], DATA_NAME)
|
||||||
}
|
: DATA_ALL[DATA_SOURCE];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Now return the data.
|
// Now return the data.
|
||||||
return DATA_SELECTED;
|
DATA_RETURNED[`source`] =
|
||||||
}
|
CLOUD != 0
|
||||||
|
? CLOUD > 0
|
||||||
|
? `sync`
|
||||||
|
: `local`
|
||||||
|
: (DATA[`sync`] ? DATA[`sync`].length <= 0 : DATA[`sync`])
|
||||||
|
? `sync`
|
||||||
|
: `local`;
|
||||||
|
DATA_RETURNED[`value`] = DATA[DATA_RETURNED[`source`]];
|
||||||
|
|
||||||
// Read data from local and sync storage (asynchronous operations)
|
return DATA_RETURNED[`value`];
|
||||||
try {
|
|
||||||
if (CLOUD <= 0) {
|
|
||||||
[DATA_ALL[`local`]] = await Promise.all([read_database(-1)]);
|
|
||||||
}
|
|
||||||
if (CLOUD >= 0) {
|
|
||||||
[DATA_ALL[`sync`]] = await Promise.all([read_database(1)]);
|
|
||||||
}
|
|
||||||
} catch ({ name, message }) {
|
|
||||||
logging.error(name, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let's get through everything and then determine which one has…
|
|
||||||
Object.keys(DATA_ALL).forEach((DATA_SOURCE) => {
|
|
||||||
if (DATA_ALL[DATA_SOURCE]) {
|
|
||||||
DATA[DATA_SOURCE] = DATA_NAME
|
|
||||||
? find_data(DATA_ALL[DATA_SOURCE], DATA_NAME, PARAMETER_TEST)
|
|
||||||
: DATA_ALL[DATA_SOURCE];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Now return the data.
|
|
||||||
DATA_RETURNED[`source`] =
|
|
||||||
CLOUD != 0
|
|
||||||
? CLOUD > 0
|
|
||||||
? `sync`
|
|
||||||
: `local`
|
|
||||||
: (DATA[`sync`] ? DATA[`sync`].length <= 0 : DATA[`sync`])
|
|
||||||
? `sync`
|
|
||||||
: `local`;
|
|
||||||
DATA_RETURNED[`value`] = DATA[DATA_RETURNED[`source`]];
|
|
||||||
|
|
||||||
return DATA_RETURNED[`value`];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* More enhanced searching.
|
/* More enhanced searching.
|
||||||
|
@ -187,67 +146,81 @@ export async function read(DATA_NAME, CLOUD = 0, PARAMETER_TEST = null) {
|
||||||
@param {Array} ADDITIONAL_PLACES additional places to search
|
@param {Array} ADDITIONAL_PLACES additional places to search
|
||||||
@return {Array} the results
|
@return {Array} the results
|
||||||
*/
|
*/
|
||||||
export function search(SOURCE, TERM, VALUE, ADDITIONAL_PLACES, STRICT = false) {
|
export async function search(SOURCE, TERM, ADDITIONAL_PLACES, STRICT = false) {
|
||||||
let DATA = read(SOURCE);
|
let DATA = await read(SOURCE);
|
||||||
let RESULTS;
|
let RESULTS;
|
||||||
|
|
||||||
if (DATA) {
|
if (DATA) {
|
||||||
RESULTS = {};
|
RESULTS = {};
|
||||||
|
|
||||||
if (TERM) {
|
if (TERM) {
|
||||||
// Sequentially search through the data, first by key.
|
// Sequentially search through the data, first by key.
|
||||||
for (let DATA_NAME in Object.keys(DATA)) {
|
let key_number = {"total": (Object.keys(DATA)).length, "current": 0};
|
||||||
if (STRICT) {
|
|
||||||
if (
|
|
||||||
STRICT
|
|
||||||
? DATA_NAME == TERM
|
|
||||||
: DATA_NAME.includes(TERM) || TERM.includes(DATA_NAME)
|
|
||||||
) {
|
|
||||||
RESULTS[`DATA_NAME`] = DATA[DATA_NAME];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then, get the additional places.
|
while (key_number[`current`] < key_number[`total`]) {
|
||||||
if (
|
let DATA_NAME = (Object.keys(DATA))[key_number[`current`]]
|
||||||
(ADDITIONAL_PLACES != null ? Array.isArray(ADDITIONAL_PLACES) : false)
|
|
||||||
? ADDITIONAL_PLACES.length > 0
|
|
||||||
: false
|
|
||||||
) {
|
|
||||||
for (let FIELD_NAME in ADDITIONAL_PLACES) {
|
|
||||||
let RESULT = read(SOURCE, 0, {
|
|
||||||
field: FIELD_NAME,
|
|
||||||
"test value": TERM,
|
|
||||||
});
|
|
||||||
if (RESULT) {
|
|
||||||
RESULTS = Object.assign(
|
|
||||||
{},
|
|
||||||
RESULTS,
|
|
||||||
search(SOURCE, null, RESULT, null, true),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (VALUE) {
|
|
||||||
for (let ENTRY in (typeof SOURCE).includes(`obj`) &&
|
|
||||||
!Array.isArray(SOURCE) &&
|
|
||||||
SOURCE != null
|
|
||||||
? Object.keys(SOURCE)
|
|
||||||
: SOURCE) {
|
|
||||||
if (
|
|
||||||
(typeof SOURCE).includes(`obj`) && !Array.isArray(SOURCE)
|
|
||||||
? SOURCE[ENTRY] == VALUE
|
|
||||||
: false
|
|
||||||
) {
|
|
||||||
RESULTS[ENTRY] = VALUE;
|
|
||||||
} else if (SOURCE[ENTRY] == VALUE) {
|
|
||||||
RESULTS[SOURCE.indexOf(ENTRY)] = VALUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return RESULTS;
|
if (
|
||||||
|
STRICT
|
||||||
|
? DATA_NAME == TERM
|
||||||
|
: (DATA_NAME.includes(TERM) || TERM.includes(DATA_NAME))
|
||||||
|
) {
|
||||||
|
RESULTS[DATA_NAME] = DATA[DATA_NAME];
|
||||||
|
}
|
||||||
|
|
||||||
|
key_number[`current`]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then, get the additional places.
|
||||||
|
if (
|
||||||
|
(ADDITIONAL_PLACES != null ? Array.isArray(ADDITIONAL_PLACES) : false)
|
||||||
|
? ADDITIONAL_PLACES.length > 0
|
||||||
|
: false
|
||||||
|
) {
|
||||||
|
for (let PARAMETER_PRIORITY_NUMBER = 0; PARAMETER_PRIORITY_NUMBER < ADDITIONAL_PLACES.length; PARAMETER_PRIORITY_NUMBER++) {
|
||||||
|
// Recursively search
|
||||||
|
RESULTS = Object.assign({}, RESULTS, search(SOURCE, TERM, ADDITIONAL_PLACES[PARAMETER_PRIORITY_NUMBER], STRICT));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else if (((typeof ADDITIONAL_PLACES).includes(`str`) && (ADDITIONAL_PLACES)) ? ADDITIONAL_PLACES.trim() : false) {
|
||||||
|
// Perform a sequential search on the data.
|
||||||
|
if ((typeof DATA).includes(`obj`) && !Array.isArray(DATA) && SOURCE != null) {
|
||||||
|
let VALUE = {};
|
||||||
|
VALUE[`test`] = TERM;
|
||||||
|
|
||||||
|
for (let DICTIONARY_INDEX = 0; DICTIONARY_INDEX < (Object.keys(DATA)).length; DICTIONARY_INDEX) {
|
||||||
|
VALUE[`parent`] = DATA[(Object.keys(DATA))[DICTIONARY_INDEX]];
|
||||||
|
|
||||||
|
if (((typeof VALUE[`parent`]).includes(`obj`) && !Array.isArray(VALUE[`parent`]) && VALUE[`parent`] != null) ? (Object.keys(VALUE[`parent`])).length > 0 : false ) {
|
||||||
|
VALUE[`current`] = (VALUE[`parent`])[`test`];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VALUE[`current`]) {
|
||||||
|
// Add the data.
|
||||||
|
RESULTS[(Object.keys(DATA))[DICTIONARY_INDEX]] = DATA;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
for (let ELEMENT_INDEX = 0; ELEMENT_INDEX < DATA.length; ELEMENT_INDEX++) {
|
||||||
|
if (
|
||||||
|
((STRICT || (typeof DATA[ELEMENT_INDEX]).includes(`num`)) && DATA[ELEMENT_INDEX] == TERM) ||
|
||||||
|
((!STRICT && !((typeof DATA[ELEMENT_INDEX]).includes(`num`)))
|
||||||
|
? (TERM.includes(DATA[ELEMENT_INDEX]) || DATA[ELEMENT_INDEX].includes(TERM) ||
|
||||||
|
(typeof(DATA[ELEMENT_INDEX])).includes(`str`)
|
||||||
|
? new RegExp(DATA[ELEMENT_INDEX]).test(TERM)
|
||||||
|
: false
|
||||||
|
) : false
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
RESULTS[SOURCE] = DATA;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RESULTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the data on the selected prefname.
|
/* Write the data on the selected prefname.
|
||||||
|
@ -257,74 +230,74 @@ export function search(SOURCE, TERM, VALUE, ADDITIONAL_PLACES, STRICT = false) {
|
||||||
@param {int} CLOUD store in the cloud; otherwise set to automatic
|
@param {int} CLOUD store in the cloud; otherwise set to automatic
|
||||||
*/
|
*/
|
||||||
export function write(PATH, DATA, CLOUD = -1) {
|
export function write(PATH, DATA, CLOUD = -1) {
|
||||||
let DATA_INJECTED = {};
|
let DATA_INJECTED = {};
|
||||||
|
|
||||||
/* Forcibly write the data to chrome database
|
/* Forcibly write the data to chrome database
|
||||||
|
|
||||||
@param {object} DATA the data
|
@param {object} DATA the data
|
||||||
@param {number} CLOUD the storage
|
@param {number} CLOUD the storage
|
||||||
*/
|
*/
|
||||||
function write_database(DATA, CLOUD = 0) {
|
function write_database(DATA, CLOUD = 0) {
|
||||||
// If CLOUD is set to 0, it should automatically determine where the previous source of data was taken from.
|
// If CLOUD is set to 0, it should automatically determine where the previous source of data was taken from.
|
||||||
|
|
||||||
if (CLOUD > 0) {
|
if (CLOUD > 0) {
|
||||||
chrome.storage.sync.set(DATA);
|
chrome.storage.sync.set(DATA);
|
||||||
} else if (CLOUD < 0) {
|
} else if (CLOUD < 0) {
|
||||||
chrome.storage.local.set(DATA);
|
chrome.storage.local.set(DATA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Appropriately nest and merge the data.
|
/* Appropriately nest and merge the data.
|
||||||
|
|
||||||
@param {object} EXISTING the original data
|
@param {object} EXISTING the original data
|
||||||
@param {object} PATH the subpath
|
@param {object} PATH the subpath
|
||||||
@param {object} VALUE the value
|
@param {object} VALUE the value
|
||||||
@return {object} the updated data
|
@return {object} the updated data
|
||||||
*/
|
*/
|
||||||
function nest(EXISTING, SUBPATH, VALUE) {
|
function nest(EXISTING, SUBPATH, VALUE) {
|
||||||
let DATABASE = EXISTING;
|
let DATABASE = EXISTING;
|
||||||
|
|
||||||
// Get the current path.
|
// Get the current path.
|
||||||
let PATH = {};
|
let PATH = {};
|
||||||
PATH[`current`] = String(SUBPATH.shift()).trim();
|
PATH[`current`] = String(SUBPATH.shift()).trim();
|
||||||
PATH[`target`] = SUBPATH;
|
PATH[`target`] = SUBPATH;
|
||||||
|
|
||||||
if (PATH[`target`].length > 0) {
|
if (PATH[`target`].length > 0) {
|
||||||
if (DATABASE[PATH[`current`]] == null) {
|
if (DATABASE[PATH[`current`]] == null) {
|
||||||
DATABASE[PATH[`current`]] = {};
|
DATABASE[PATH[`current`]] = {};
|
||||||
}
|
}
|
||||||
DATABASE[PATH[`current`]] = nest(
|
DATABASE[PATH[`current`]] = nest(
|
||||||
DATABASE[PATH[`current`]],
|
DATABASE[PATH[`current`]],
|
||||||
PATH[`target`],
|
PATH[`target`],
|
||||||
VALUE,
|
VALUE,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
DATABASE[PATH[`current`]] = VALUE;
|
DATABASE[PATH[`current`]] = VALUE;
|
||||||
}
|
}
|
||||||
// Return the value.
|
// Return the value.
|
||||||
return DATABASE;
|
return DATABASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
read(null, CLOUD).then((DATA_ALL) => {
|
read(null, CLOUD).then((DATA_ALL) => {
|
||||||
// handle empty collected data.
|
// handle empty collected data.
|
||||||
if (!DATA_ALL) {
|
if (!DATA_ALL) {
|
||||||
DATA_ALL = {};
|
DATA_ALL = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
let DATA_NAME = PATH;
|
let DATA_NAME = PATH;
|
||||||
|
|
||||||
// Convert the entered prefname to an array if it is not one.
|
// Convert the entered prefname to an array if it is not one.
|
||||||
if (!(typeof SUBPATH).includes(`object`)) {
|
if (!(typeof SUBPATH).includes(`object`)) {
|
||||||
// Split what is not an object.
|
// Split what is not an object.
|
||||||
DATA_NAME = String(PATH).trim().split(",");
|
DATA_NAME = String(PATH).trim().split(",");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge!
|
// Merge!
|
||||||
DATA_INJECTED = nest(DATA_ALL, DATA_NAME, DATA);
|
DATA_INJECTED = nest(DATA_ALL, DATA_NAME, DATA);
|
||||||
|
|
||||||
// Write!
|
// Write!
|
||||||
write_database(DATA_INJECTED, CLOUD);
|
write_database(DATA_INJECTED, CLOUD);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dangerous: Resets all data or a domain's data.
|
/* Dangerous: Resets all data or a domain's data.
|
||||||
|
@ -335,58 +308,58 @@ export function write(PATH, DATA, CLOUD = -1) {
|
||||||
@return {boolean} the user's confirmation
|
@return {boolean} the user's confirmation
|
||||||
*/
|
*/
|
||||||
export function forget(preference, subpreference, CLOUD = 0) {
|
export function forget(preference, subpreference, CLOUD = 0) {
|
||||||
let forget_action = false;
|
let forget_action = false;
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
// Import alerts module.
|
// Import alerts module.
|
||||||
let alerts = (await import(chrome.runtime.getURL(`gui/scripts/alerts.js`)))[
|
let alerts = (await import(chrome.runtime.getURL(`gui/scripts/alerts.js`)))[
|
||||||
`alerts`
|
`alerts`
|
||||||
];
|
];
|
||||||
|
|
||||||
// Confirm the action.
|
// Confirm the action.
|
||||||
let forget_action = alerts.confirm_action();
|
let forget_action = alerts.confirm_action();
|
||||||
|
|
||||||
if (forget_action) {
|
if (forget_action) {
|
||||||
if (preference) {
|
if (preference) {
|
||||||
if (subpreference) {
|
if (subpreference) {
|
||||||
// Get the data.
|
// Get the data.
|
||||||
data = read(preference, CLOUD);
|
data = read(preference, CLOUD);
|
||||||
|
|
||||||
// Should only run when existent
|
// Should only run when existent
|
||||||
if (data[subpreference]) {
|
if (data[subpreference]) {
|
||||||
delete data[subpreference];
|
delete data[subpreference];
|
||||||
write([preference, subpreference], data, CLOUD);
|
write([preference, subpreference], data, CLOUD);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Remove that particular data.
|
// Remove that particular data.
|
||||||
if (CLOUD <= 0) {
|
if (CLOUD <= 0) {
|
||||||
chrome.storage.local.get(null, (data) => {
|
chrome.storage.local.get(null, (data) => {
|
||||||
delete data[preference];
|
delete data[preference];
|
||||||
|
|
||||||
chrome.storage.local.set(data, (result) => {});
|
chrome.storage.local.set(data, (result) => {});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (CLOUD >= 0) {
|
if (CLOUD >= 0) {
|
||||||
chrome.storage.sync.get(null, (data) => {
|
chrome.storage.sync.get(null, (data) => {
|
||||||
delete data[preference];
|
delete data[preference];
|
||||||
|
|
||||||
chrome.storage.sync.set(data, (result) => {});
|
chrome.storage.sync.set(data, (result) => {});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Clear the data storage.
|
// Clear the data storage.
|
||||||
if (CLOUD >= 0) {
|
if (CLOUD >= 0) {
|
||||||
chrome.storage.sync.clear();
|
chrome.storage.sync.clear();
|
||||||
}
|
}
|
||||||
if (CLOUD <= 0) {
|
if (CLOUD <= 0) {
|
||||||
chrome.storage.local.clear();
|
chrome.storage.local.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
return forget_action;
|
return forget_action;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the storage.
|
/* Initialize the storage.
|
||||||
|
@ -394,71 +367,71 @@ export function forget(preference, subpreference, CLOUD = 0) {
|
||||||
@param {dictionary} data this build's managed data
|
@param {dictionary} data this build's managed data
|
||||||
*/
|
*/
|
||||||
export function init(data) {
|
export function init(data) {
|
||||||
let PREFERENCES_ALL = {};
|
let PREFERENCES_ALL = {};
|
||||||
PREFERENCES_ALL[`build`] = data;
|
PREFERENCES_ALL[`build`] = data;
|
||||||
|
|
||||||
// Read all data.
|
// Read all data.
|
||||||
chrome.storage.managed.get(null, function (DATA_MANAGED) {
|
chrome.storage.managed.get(null, function (DATA_MANAGED) {
|
||||||
PREFERENCES_ALL[`managed`] = DATA_MANAGED;
|
PREFERENCES_ALL[`managed`] = DATA_MANAGED;
|
||||||
});
|
});
|
||||||
|
|
||||||
chrome.storage.local.get(null, function (DATA_LOCAL) {
|
chrome.storage.local.get(null, function (DATA_LOCAL) {
|
||||||
PREFERENCES_ALL[`local`] = DATA_LOCAL;
|
PREFERENCES_ALL[`local`] = DATA_LOCAL;
|
||||||
});
|
});
|
||||||
|
|
||||||
chrome.storage.sync.get(null, function (DATA_SYNC) {
|
chrome.storage.sync.get(null, function (DATA_SYNC) {
|
||||||
PREFERENCES_ALL[`sync`] = DATA_SYNC;
|
PREFERENCES_ALL[`sync`] = DATA_SYNC;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Merge data.
|
// Merge data.
|
||||||
// Managed > Synchronized > Imported > Local
|
// Managed > Synchronized > Imported > Local
|
||||||
|
|
||||||
if (PREFERENCES_ALL[`managed`]) {
|
if (PREFERENCES_ALL[`managed`]) {
|
||||||
Object.keys(PREFERENCES_ALL[`managed`]).forEach((item) => {
|
Object.keys(PREFERENCES_ALL[`managed`]).forEach((item) => {
|
||||||
let PREFERENCE = { name: item, existing: false };
|
let PREFERENCE = { name: item, existing: false };
|
||||||
|
|
||||||
if (PREFERENCES_ALL[`sync`]) {
|
if (PREFERENCES_ALL[`sync`]) {
|
||||||
PREFERENCE[`existing`] = PREFERENCES_ALL[`sync`].hasOwnProperty(
|
PREFERENCE[`existing`] = PREFERENCES_ALL[`sync`].hasOwnProperty(
|
||||||
PREFERENCE[`name`],
|
PREFERENCE[`name`],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PREFERENCE[`existing`]) {
|
if (!PREFERENCE[`existing`]) {
|
||||||
// Do not allow synchronized data to interfere with managed data.
|
// Do not allow synchronized data to interfere with managed data.
|
||||||
forget(PREFERENCE[`name`]);
|
forget(PREFERENCE[`name`]);
|
||||||
write(
|
write(
|
||||||
PREFERENCE[`name`],
|
PREFERENCE[`name`],
|
||||||
PREFERENCES_ALL[`managed`][PREFERENCE[`name`]],
|
PREFERENCES_ALL[`managed`][PREFERENCE[`name`]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import build data
|
// Import build data
|
||||||
if (PREFERENCES_ALL[`build`]) {
|
if (PREFERENCES_ALL[`build`]) {
|
||||||
Object.keys(PREFERENCES_ALL[`build`]).forEach((item) => {
|
Object.keys(PREFERENCES_ALL[`build`]).forEach((item) => {
|
||||||
let PREFERENCE = { name: item, existing: false };
|
let PREFERENCE = { name: item, existing: false };
|
||||||
|
|
||||||
PREFERENCE[`existing`] =
|
PREFERENCE[`existing`] =
|
||||||
(PREFERENCES_ALL[`sync`]
|
(PREFERENCES_ALL[`sync`]
|
||||||
? PREFERENCES_ALL[`sync`].hasOwnProperty(PREFERENCE[`name`])
|
? PREFERENCES_ALL[`sync`].hasOwnProperty(PREFERENCE[`name`])
|
||||||
: false) ||
|
: false) ||
|
||||||
(PREFERENCES_ALL[`managed`]
|
(PREFERENCES_ALL[`managed`]
|
||||||
? PREFERENCES_ALL[`managed`].hasOwnProperty(PREFERENCE[`name`])
|
? PREFERENCES_ALL[`managed`].hasOwnProperty(PREFERENCE[`name`])
|
||||||
: false) ||
|
: false) ||
|
||||||
(PREFERENCES_ALL[`local`]
|
(PREFERENCES_ALL[`local`]
|
||||||
? PREFERENCES_ALL[`local`].hasOwnProperty(PREFERENCE[`local`])
|
? PREFERENCES_ALL[`local`].hasOwnProperty(PREFERENCE[`local`])
|
||||||
: false);
|
: false);
|
||||||
|
|
||||||
if (!PREFERENCE[`existing`]) {
|
if (!PREFERENCE[`existing`]) {
|
||||||
write(
|
write(
|
||||||
PREFERENCE[`name`],
|
PREFERENCE[`name`],
|
||||||
PREFERENCES_ALL[`build`][PREFERENCE[`name`]],
|
PREFERENCES_ALL[`build`][PREFERENCE[`name`]],
|
||||||
-1,
|
-1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -467,7 +440,7 @@ Run a script when the browser storage has been changed.
|
||||||
@param {object} reaction the function to run
|
@param {object} reaction the function to run
|
||||||
*/
|
*/
|
||||||
export function observe(reaction) {
|
export function observe(reaction) {
|
||||||
chrome.storage.onChanged.addListener((changes, namespace) => {
|
chrome.storage.onChanged.addListener((changes, namespace) => {
|
||||||
reaction(changes, namespace);
|
reaction(changes, namespace);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue