fixed class referencing

This commit is contained in:
buzz-lightsnack-2007 2024-03-31 15:43:28 +08:00
parent 6a1ea8eb7d
commit 543fe2f913
9 changed files with 383 additions and 377 deletions

View file

@ -13,7 +13,9 @@ export default class logging {
static error(ERROR_CODE, ERROR_MESSAGE, critical = true) { static error(ERROR_CODE, ERROR_MESSAGE, critical = true) {
(async () => { (async () => {
// Import the templating. // Import the templating.
const texts = await import(chrome.runtime.getURL("gui/scripts/read.js")); const texts = (
await import(chrome.runtime.getURL("gui/scripts/read.js"))
)[`texts`];
// Display the error message. // Display the error message.
console.error(texts.read(`error_msg`, [ERROR_CODE, ERROR_MESSAGE])); console.error(texts.read(`error_msg`, [ERROR_CODE, ERROR_MESSAGE]));

View file

@ -1,12 +1,11 @@
import {windowman} from '../../windowman.JS'; import { windowman } from "../../windowman.JS";
function redirect() { function redirect() {
new windowman(`gui/pages/settings.htm`); windowman.new(`gui/pages/settings.htm`);
window.close(); window.close();
} }
function main() { function main() {
redirect(); redirect();
} }

View file

@ -1,14 +1,13 @@
// Open the settings in a pop-up window. // Open the settings in a pop-up window.
import {windowman} from '../../windowman.JS'; import { windowman } from "../../windowman.JS";
function redirect() { function redirect() {
new windowman(`gui/pages/settings.htm`); windowman.new(`gui/pages/settings.htm`);
window.close(); window.close();
} }
function main() { function main() {
redirect(); redirect();
} }

View file

@ -1,15 +1,25 @@
/* Settings.js /* Settings.js
Build the interface for the settings Build the interface for the settings
*/ */
// Import modules. // Import modules.
import { windowman } from "../windowman.js"; //import { windowman } from "../windowman.js";
let secretariat = await import(chrome.runtime.getURL("scripts/secretariat.js"));
async function build() {
let secretariat = (
await import(chrome.runtime.getURL("scripts/secretariat.js"))
).secretariat;
let windowman = (
await import(chrome.runtime.getURL("gui/scripts/windowman.js"))
).windowman;
let window = new windowman();
}
/* /*
Arrange the interface. Arrange the interface.
*/ */
function arrange() { /*function arrange() {
async function openLast() { async function openLast() {
let last_opened = ( let last_opened = (
await Promise.all([secretariat.read([`view`, window.location.href], 1)]) await Promise.all([secretariat.read([`view`, window.location.href], 1)])
@ -26,17 +36,24 @@ function arrange() {
openLast(); openLast();
} }
/*
Define the mapping of each button.
*/
function events() {
windowman.events();
function main() {
windowman.fill();
events();
arrange();
}*/
/*
Define the mapping of each button.
*/
function events() {
if (document.querySelector(`[data-action="filters,update"]`)) { if (document.querySelector(`[data-action="filters,update"]`)) {
document document
.querySelector(`[data-action="filters,update"]`) .querySelector(`[data-action="filters,update"]`)
.addEventListener(`click`, async () => { .addEventListener(`click`, async () => {
let filters = await import(chrome.runtime.getURL(`scripts/filters.js`)); let filters = (
await import(chrome.runtime.getURL(`scripts/filters.js`))
).default;
filters.update(); filters.update();
}); });
} }
@ -44,19 +61,22 @@ function events() {
document document
.querySelector(`[data-action="storage,clear"]`) .querySelector(`[data-action="storage,clear"]`)
.addEventListener(`click`, async () => { .addEventListener(`click`, async () => {
let storage = await import( let storage = (
chrome.runtime.getURL(`scripts/secretariat.js`) await import(chrome.runtime.getURL(`scripts/secretariat.js`))
); )["secretariat"];
storage.forget(`sites`); storage.forget(`sites`);
}); });
} }
} }
function main() { //main();
windowman.prepare(); function load() {
windowman.fill(); document.addEventListener("DOMContentLoaded", function () {
M.AutoInit();
});
build();
events(); events();
arrange();
} }
main(); load();

View file

@ -1,76 +1,144 @@
/* windowman /* windowman
Window management */ Window and window content management */
import texts from "./read.js"; import texts from "./read.js";
class windowman { class windowman {
/* Initialize the window frame. */ static new(URL, height, width) {
static prepare() {
try {
let UI = {
library: [
chrome.runtime.getURL("gui/styles/interface.external.css"),
chrome.runtime.getURL("gui/styles/ui.css"),
],
script: chrome.runtime.getURL(
"gui/scripts/external/interface.external.js",
),
};
UI.library.forEach((source) => {
$(`head`).append(
`<link rel="stylesheet" type="text/css" href="${source}">`,
);
});
$(`head`).append(`<script type="module" src="${UI.script}"></script>`);
} catch (error) {
console.error(texts.localized(`error_fileNotFound`, [error]));
}
// Prevent scaling, similar to a real window.
$(`head`).append(
`<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />`,
);
}
constructor(URL, height, width) {
this.window = chrome.windows.create({ this.window = chrome.windows.create({
url: chrome.runtime.getURL(URL), url: chrome.runtime.getURL(URL),
type: "popup", type: "popup",
width: width ? parseInt(width) : 400, width: width ? parseInt(width) : 600,
height: height ? parseInt(height) : 600, height: height ? parseInt(height) : 600,
}); });
} }
static fill() { // Prepare the window with its metadata.
function text() { constructor() {
let text_elements = document.querySelectorAll("[data-text]"); function headers() {
let UI = {
library: [
chrome.runtime.getURL(
"gui/styles/external/mdi/materialdesignicons.min.css",
),
chrome.runtime.getURL(
"gui/styles/external/materialize/css/materialize.css",
),
chrome.runtime.getURL("gui/styles/ui.css"),
],
};
text_elements.forEach((text_element) => { UI.library.forEach((source) => {
let text_inserted = texts.localized( let metadata_element = document.createElement(`link`);
text_element.getAttribute(`data-text`), metadata_element.setAttribute(`rel`, `stylesheet`);
false, metadata_element.setAttribute(`type`, `text/css`);
text_element.hasAttribute(`data-text-parameter`) metadata_element.setAttribute(`href`, source);
? text_element.getAttribute(`data-text-parameter`).split(",") document.querySelector(`head`).appendChild(metadata_element);
: null,
);
if (!text_inserted) {
text_inserted = texts.localized(
`term_`.concat(text_element.getAttribute(`data-text`)),
);
}
if (text_element.tagName.toLowerCase().includes(`input`)) {
text_element.setAttribute(`placholder`, text_inserted);
} else {
text_element.innerText = text_inserted;
}
}); });
} }
function storage() { // Get the window.
(async () => { this[`metadata`] = chrome.windows.getCurrent();
/*
window_metadata[`id`] = window.id;
window_metadata[`focused`] = window.focused;
window_metadata[`state`] = window.state;
window_metadata[`type`] = window.type;
window_metadata[`incognito`] = window.incognito;
window_metadata[`alwaysOnTop`] = window.alwaysOnTop;
window_metadata[`sessionId`] = window.sessionId;
window_metadata[`tabs`] = window.tabs;*/
/* Fill in data and events. */
function appearance() {
function icons() {
let target_elements = document.querySelectorAll(`[data-icon]`);
target_elements.forEach((element) => {
// Get the content before removing it.
let element_data = {};
// Swap the placement of the existing content.
function swap() {
element_data[`content`] = element.innerHTML;
element.innerHTML = ``;
let element_text = document.createElement(`span`);
element_text.innerHTML = element_data[`content`];
element.appendChild(element_text);
}
// Add the icon.
function iconify() {
// Get the icon.
element_data[`icon`] = element.getAttribute(`data-icon`);
// Get the icon.
let icon_element = document.createElement(`i`);
icon_element.className = `mdi mdi-`.concat(element_data[`icon`]);
element.prepend(icon_element);
}
swap();
iconify();
});
}
function text() {
let text_elements = {};
text_elements[`content`] = document.querySelectorAll("[for]");
text_elements[`alt`] = document.querySelectorAll("[alt-for]");
text_elements[`title`] = document.querySelectorAll("[title-for]");
text_elements[`content`].forEach((text_element) => {
let text_inserted = texts.localized(
text_element.getAttribute(`for`),
false,
text_element.hasAttribute(`for-parameter`)
? text_element.getAttribute(`for-parameter`).split(",")
: null,
);
if (!text_inserted) {
text_inserted = texts.localized(
`term_`.concat(text_element.getAttribute(`for`)),
);
}
if (text_element.tagName.toLowerCase().includes(`input`)) {
text_element.setAttribute(`placholder`, text_inserted);
} else {
text_element.innerText = text_inserted;
}
});
delete text_elements[`content`];
Object.keys(text_elements).forEach((key) => {
if (text_elements[key]) {
text_elements[key].forEach((text_element) => {
let text_inserted = texts.localized(
text_element.getAttribute(key.concat(`-for`)),
false,
text_element.hasAttribute(key.concat(`for-parameter`))
? text_element
.getAttribute(key.concat(`for-parameter`))
.split(",")
: null,
);
if (!text_inserted) {
text_inserted = texts.localized(
`term_`.concat(text_element.getAttribute(key.concat(`-for`))),
);
}
text_element.setAttribute(key, text_inserted);
});
}
});
}
async function storage() {
// Import the module. // Import the module.
const secretariat = await import( const secretariat = await import(
chrome.runtime.getURL("scripts/secretariat.js") chrome.runtime.getURL("scripts/secretariat.js")
@ -108,18 +176,17 @@ class windowman {
} }
}); });
}); });
})(); }
text();
icons();
storage();
} }
text(); // Adds events to the window.
storage(); function events() {
} /* Add events related to storage. */
async function storage() {
/* Add click events. */
static events() {
/* Add events related to storage. */
function storage() {
(async () => {
// Import the module. // Import the module.
const secretariat = await import( const secretariat = await import(
chrome.runtime.getURL("scripts/secretariat.js") chrome.runtime.getURL("scripts/secretariat.js")
@ -160,201 +227,97 @@ class windowman {
input_element.addEventListener("change", element[`event`]); input_element.addEventListener("change", element[`event`]);
}); });
})(); }
}
/* Make it feel more like a native window. */ /* Map buttons to their corresponding action buttons. */
function functionality() { function actions() {
/* Adjust the interface based on events. */ function links() {
function changeUI() { let buttons = document.querySelectorAll("button[href]");
function tabs() {
let menus = document.querySelectorAll("menu[role=tablist]");
if (menus) { if (buttons) {
menus.forEach((menu) => { buttons.forEach((button) => {
let buttons = menu.querySelectorAll("button, a"); let event = function () {
// Get the data from the button.
let target = {};
target[`source`] = this.getAttribute(`href`);
if (buttons) { // Get the correct path.
buttons.forEach((button) => { target[`path`] = (
let event = function () { !target[`source`].includes(`://`)
// Prevent selection. ? window.location.pathname
let MENU = this.parentElement; .split(`/`)
let BUTTONS = MENU.querySelectorAll("button, a"); .slice(0, -1)
.join(`/`)
.concat(`/`)
: ``
).concat(target[`source`]);
BUTTONS.forEach((BUTTON) => { windowman.new(
BUTTON.setAttribute( target[`path`],
`aria-selected`, this.getAttribute(`tab-height`)
String( ? this.getAttribute(`tab-height`)
BUTTON.getAttribute(`for`) == : null,
this.getAttribute(`for`), this.getAttribute(`tab-width`)
), ? this.getAttribute(`tab-width`)
); : null,
}); );
};
button.addEventListener("click", event);
});
}
}
let CONTAINER = document.getElementById( links();
MENU.getAttribute(`for`), }
);
let SECTIONS = CONTAINER.querySelectorAll(
`#${CONTAINER.id} > section`,
);
SECTIONS.forEach((SECTION) => { /*
// SECTION.setAttribute(`hidden`, true); Update the interface based on the storage data changes.
*/
async function updates() {
// Import the module.
const secretariat = await import(
chrome.runtime.getURL("scripts/secretariat.js")
);
if (!this.getAttribute(`for`).includes(SECTION.id)) { // Get the storage data.
SECTION.setAttribute( let storage_data = await secretariat.read();
`hidden`,
this.getAttribute(`for`).includes(SECTION.id),
);
} else {
SECTION.removeAttribute(`hidden`);
}
});
// Save. async function update_interface() {
(async () => { let input_elements = document.querySelectorAll("[data-enable]");
const secretariat = await import(
chrome.runtime.getURL("scripts/secretariat.js")
);
// Write the data. if (input_elements) {
secretariat.write( input_elements.forEach((input_element) => {
[`view`, window.location.href], if (input_element.getAttribute("data-enable")) {
parseInt(this.getAttribute(`tab`)), (async () => {
1, input_element.disabled =
); (await secretariat.read(
})(); input_element.getAttribute("data-enable"),
}; )) == null ||
(await secretariat.read(
button.addEventListener("click", event); input_element.getAttribute("data-enable"),
}); ));
})();
} }
}); });
} }
} }
tabs(); // Update the input elements.
} secretariat.observe((what) => {
update_interface();
});
document.addEventListener("contextmenu", (event) =>
event.preventDefault(),
);
changeUI();
}
/* Map buttons to their corresponding action buttons. */
function actions() {
function links() {
let buttons = document.querySelectorAll("button[href]");
if (buttons) {
buttons.forEach((button) => {
let event = function () {
// Get the data from the button.
let file = {};
file[`target`] = this.getAttribute(`href`);
// Check if the file exists to only open it when it is the case.
function testUrl(URL) {
// Code from https://stackoverflow.com/questions/3646914/how-do-i-check-if-file-exists-in-jquery-or-pure-javascript
const HTTP = new XMLHttpRequest();
try {
HTTP.open(`HEAD`, URL, false);
HTTP.send();
return HTTP.status != 404;
} catch (error) {
return false;
}
}
if (!file[`target`].includes(`://`)) {
// Get the current path.
file[`path`] = window.location.pathname.split(`/`);
file[`path`] =
file[`path`].slice(0, file[`path`].length - 1).join(`/`) +
`/`;
file[`location`] = file[`path`].concat(file[`target`]);
} else {
file[`location`] = file[`target`];
}
let open_combinations = [``, `.htm`, `.html`];
for (
let open_combination = 0;
open_combination < open_combinations.length;
open_combination++
) {
if (
testUrl(
file[`location`] + open_combinations[open_combination],
)
) {
new windowman(
file[`location`] + open_combinations[open_combination],
this.getAttribute(`tab-height`)
? this.getAttribute(`tab-height`)
: null,
this.getAttribute(`tab-width`)
? this.getAttribute(`tab-width`)
: null,
);
break;
}
}
};
button.addEventListener("click", event);
});
}
}
links();
}
/*
Update the interface based on the storage data changes.
*/
async function updates() {
// Import the module.
const secretariat = await import(
chrome.runtime.getURL("scripts/secretariat.js")
);
// Get the storage data.
let storage_data = await secretariat.read();
async function update_interface() {
let input_elements = document.querySelectorAll("[data-enable]");
if (input_elements) {
input_elements.forEach((input_element) => {
if (input_element.getAttribute("data-enable")) {
(async () => {
input_element.disabled =
(await secretariat.read(
input_element.getAttribute("data-enable"),
)) == null ||
(await secretariat.read(
input_element.getAttribute("data-enable"),
));
})();
}
});
}
}
// Update the input elements.
secretariat.observe((what) => {
update_interface(); update_interface();
}); }
update_interface(); storage();
actions();
updates();
} }
storage(); headers();
functionality(); appearance();
actions(); events();
updates();
} }
} }

View file

@ -2,7 +2,7 @@
This does not stand for "FamiCom" but instead on Finalization and Completion. This script provides installation run scripts. This does not stand for "FamiCom" but instead on Finalization and Completion. This script provides installation run scripts.
*/ */
import { read, write, init } from "./secretariat.js"; import { init } from "./secretariat.js";
let config = chrome.runtime.getURL("config/config.json"); let config = chrome.runtime.getURL("config/config.json");

View file

@ -2,102 +2,121 @@
Manage filters. Manage filters.
*/ */
/* Select the most appropriate filter based on a URL. export default class filters {
constructor() {
@param {string} URL the current URL this.all = {};
*/
export async function select(URL = window.location.href) {}
/* Update all filters or just one.
@param {string} URL the URL to update
@return {boolean} the state
*/
export async function update(URL) {
// Import the updater.
const secretariat = await import(
chrome.runtime.getURL("scripts/secretariat.js")
);
const net = await import(chrome.runtime.getURL("scripts/net.js"));
const texts = await import(chrome.runtime.getURL("gui/scripts/read.js"));
// Apparently, JS doesn't have a native queueing system, but it might best work here.
class Queue {
constructor() {
this.elements = [];
}
enqueue(element) {
this.elements.push(element);
}
dequeue() {
return this.elements.shift();
}
isEmpty() {
return this.elements.length <= 0;
}
} }
// Create a queue of the filters. /* Select the most appropriate filter based on a URL.
let filters = new Queue();
if (URL) { @param {string} URL the current URL
// Check if the URL is in a valid protocol */
if (URL.includes(`://`)) { static select(URL = window.location.href) {
// Append that to the queue. this.one = {};
filters.enqueue(URL);
}
} else {
// Add every item to the queue based on what was loaded first.
if ((await Promise.all([secretariat.read(`filters`, -1)]))[0]) {
Object.keys(
(await Promise.all([secretariat.read(`filters`, -1)]))[0],
).every((filter_URL) => {
if (filter_URL.includes(`://`)) {
filters.enqueue(filter_URL);
}
});
}
} }
if (!filters.isEmpty()) { /* Update all filters or just one.
while (!filters.isEmpty()) {
let filter_URL = filters.dequeue();
// Inform the user of download state. @param {string} URL the URL to update
console.log( @return {boolean} the state
texts.read(`settings_filters_update_status`, null, [filter_URL]), */
static update(URL) {
(async () => {
// Import the updater.
const secretariat = await import(
chrome.runtime.getURL("scripts/secretariat.js")
); );
const net = await import(chrome.runtime.getURL("scripts/net.js"));
const texts = (await import(chrome.runtime.getURL("gui/scripts/read.js")))
.default;
const alerts = (
await import(chrome.runtime.getURL("gui/scripts/alerts.js"))
).default;
// Create promise of downloading. // Apparently, JS doesn't have a native queueing system, but it might best work here.
let filter_download = net.download(filter_URL); class Queue {
filter_download constructor() {
.then((result) => { this.elements = [];
// Only work when the filter is valid. }
if (result) {
// Write the filter to storage. enqueue(element) {
secretariat.write(["filters", filter_URL], result, -1); this.elements.push(element);
console.log( }
texts.read(`settings_filters_update_status_complete`, null, [
filter_URL, dequeue() {
]), return this.elements.shift();
); }
}
}) isEmpty() {
.catch((error) => { return this.elements.length <= 0;
// Inform the user of the download failure. }
console.log( }
texts.read(`settings_filters_update_status_failure`, null, [
error, // Create a queue of the filters.
let filters = new Queue();
if (URL) {
// Check if the URL is in a valid protocol
if (URL.includes(`://`)) {
// Append that to the queue.
filters.enqueue(URL);
}
} else {
// Add every item to the queue based on what was loaded first.
if ((await Promise.all([secretariat.read(`filters`, -1)]))[0]) {
Object.keys(
(await Promise.all([secretariat.read(`filters`, -1)]))[0],
).every((filter_URL) => {
if (filter_URL.includes(`://`)) {
filters.enqueue(filter_URL);
}
});
}
}
if (!filters.isEmpty()) {
while (!filters.isEmpty()) {
let filter_URL = filters.dequeue();
// Inform the user of download state.
alerts.log(
texts.localized(`settings_filters_update_status`, null, [
filter_URL, filter_URL,
]), ]),
); );
});
} // Create promise of downloading.
} else { let filter_download = net.download(filter_URL);
// Inform the user of the download being unnecessary. filter_download
console.log(texts.read(`settings_filters_update_stop`)); .then((result) => {
// Only work when the filter is valid.
if (result) {
// Write the filter to storage.
secretariat.write(["filters", filter_URL], result, -1);
console.log(
texts.localized(
`settings_filters_update_status_complete`,
null,
[filter_URL],
),
);
}
})
.catch((error) => {
// Inform the user of the download failure.
console.log(
texts.localized(
`settings_filters_update_status_failure`,
null,
[error, filter_URL],
),
);
});
}
} else {
// Inform the user of the download being unnecessary.
alerts.warn(texts.localized(`settings_filters_update_stop`));
}
})();
} }
} }

View file

@ -27,11 +27,11 @@ export async function read(DATA_NAME, CLOUD = 0, PARAMETER_TEST = null) {
} }
/* /*
Find the data now. Get all dataset.
@param {number} SOURCE the data source @param {number} SOURCE the data source
*/ */
function read_database(SOURCE = -1) { async function read_database(SOURCE = -1) {
let data = {}; let data = {};
let data_returned; let data_returned;
@ -75,10 +75,10 @@ export async function read(DATA_NAME, CLOUD = 0, PARAMETER_TEST = null) {
/* 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
@return {object} the data @return {object} the data
*/ */
function find_data(DATA_ALL, DATA_PATH, PARAMETER_TEST) { function find_data(DATA_ALL, DATA_PATH, PARAMETER_TEST) {
// Pull the data out. // Pull the data out.
let DATA_PATH_SELECTED = String(DATA_PATH.shift()).trim(); let DATA_PATH_SELECTED = String(DATA_PATH.shift()).trim();
@ -185,9 +185,9 @@ export function write(PATH, DATA, CLOUD = -1) {
/* 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.
@ -200,11 +200,11 @@ export function write(PATH, DATA, CLOUD = -1) {
/* 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;
@ -263,7 +263,9 @@ export function forget(preference, subpreference, CLOUD = 0) {
(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`
];
// Confirm the action. // Confirm the action.
let forget_action = alerts.confirm_action(); let forget_action = alerts.confirm_action();
@ -388,7 +390,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 async 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);
}); });

View file

@ -7,8 +7,10 @@ Be sensitive to changes and update the state.
let secretariat = await import( let secretariat = await import(
chrome.runtime.getURL("scripts/secretariat.js") chrome.runtime.getURL("scripts/secretariat.js")
); );
let filters = await import(chrome.runtime.getURL("scripts/filters.js")); let filters = (await import(chrome.runtime.getURL("scripts/filters.js")))[
let reader = await import(chrome.runtime.getURL("scripts/reader.js")); `filters`
];
// let reader = await import(chrome.runtime.getURL("scripts/reader.js"));
class watchman { class watchman {
/* Check the current URL. /* Check the current URL.