feat(browser-extension): add ability to refresh database manually through popup

This commit is contained in:
wanhose 2024-08-03 14:00:42 +02:00
parent 700dfb7492
commit ca07c4c32e
7 changed files with 130 additions and 11 deletions

View File

@ -17,7 +17,10 @@ export default (server: FastifyInstance, _options: RouteShorthandOptions, done:
success: true,
});
} catch (error) {
reply.send({ success: false });
reply.send({
errors: [error.message],
success: false,
});
}
});

View File

@ -13,7 +13,10 @@ export default (server: FastifyInstance, _options: RouteShorthandOptions, done:
reply.send({ data: result, success: true });
} catch (error) {
reply.send({ success: false });
reply.send({
errors: [error.message],
success: false,
});
}
});

View File

@ -108,7 +108,44 @@
<popup-data-container>
<popup-data>
<strong data-i18n="popup_databaseVersion"></strong>
<time id="database-version"></time>
<span id="database-version"></span>
<popup-data-button
data-animation="flip"
id="refresh-database-button"
role="button"
tabindex="0"
>
<svg
aria-hidden="true"
fill="none"
height="12"
id="refresh-database-spinner"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
stroke="currentColor"
viewBox="0 0 24 24"
width="12"
>
<polyline points="1 4 1 10 7 10"></polyline>
<polyline points="23 20 23 14 17 14"></polyline>
<path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15"></path>
</svg>
<svg
aria-hidden="true"
fill="none"
height="12"
id="refresh-database-check"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
stroke="var(--color-success)"
viewBox="0 0 24 24"
width="12"
>
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
</popup-data-button>
</popup-data>
<popup-data>
<strong data-i18n="popup_extensionVersion"></strong>

View File

@ -68,7 +68,7 @@ const report = async (message, tab, callback) => {
const userAgent = message.userAgent;
const version = browser.runtime.getManifest().version;
const body = JSON.stringify({ reason, url: tab.url, userAgent, version });
const headers = { 'Content-type': 'application/json' };
const headers = { 'Cache-Control': 'no-cache', 'Content-type': 'application/json' };
const url = `${apiUrl}/report/`;
const response = await fetch(url, { body, headers, method: 'POST' });

View File

@ -1,11 +1,19 @@
/**
* @typedef {Object} ExtensionData
* @property {string[] | undefined} commonWords
* @property {string[] | undefined} fixes
* @property {Fix[] | undefined} fixes
* @property {{ domains: string[] | undefined, tags: string[] | undefined } | undefined} skips
* @property {{ classes: string[] | undefined, selectors: string[] | undefined } | undefined} tokens
*/
/**
* @typedef {Object} Fix
* @property {string} action
* @property {string} domain
* @property {string | undefined} property
* @property {string} selector
*/
/**
* @typedef {Object} RunParams
* @property {boolean | undefined} skipTriggerEvent
@ -275,9 +283,9 @@ function fix() {
document.getElementsByTagName('ion-router-outlet')[0]?.removeAttribute('inert');
for (const fix of fixes) {
const [match, selector, action, property] = fix.split('##');
const { action, domain, property, selector } = fix;
if (hostname.includes(match)) {
if (hostname.includes(domain)) {
switch (action) {
case 'click': {
const element = document.querySelector(selector);

View File

@ -63,7 +63,6 @@ async function handleContentLoaded() {
? new URL(tab.url).hostname.split('.').slice(-3).join('.').replace('www.', '')
: undefined;
const data = await browser.runtime.sendMessage({ hostname, type: 'GET_DATA' });
const next = await browser.runtime.sendMessage({ hostname, type: 'GET_HOSTNAME_STATE' });
state = { ...(next ?? state), tabId: tab?.id };
@ -73,9 +72,8 @@ async function handleContentLoaded() {
const contributeButtonElement = document.getElementById('contribute-option');
contributeButtonElement?.addEventListener('click', handleLinkRedirect);
const databaseVersionElement = document.getElementById('database-version');
if (data.version) databaseVersionElement.innerText = data.version;
else databaseVersionElement.style.setProperty('display', 'none');
const databaseRefreshButtonElement = document.getElementById('refresh-database-button');
databaseRefreshButtonElement?.addEventListener('click', handleDatabaseRefresh);
const extensionVersionElement = document.getElementById('extension-version');
extensionVersionElement.innerText = browser.runtime.getManifest().version;
@ -98,6 +96,34 @@ async function handleContentLoaded() {
settingsButtonElement.addEventListener('click', handleSettingsClick);
translate();
updateDatabaseVersion();
}
/**
* @async
* @description Refresh the database
* @param {MouseEvent} event
*/
async function handleDatabaseRefresh(event) {
const target = event.currentTarget;
const checkIcon = target.querySelector('#refresh-database-check');
const spinnerIcon = target.querySelector('#refresh-database-spinner');
target.setAttribute('data-refreshing', 'true');
target.setAttribute('disabled', 'true');
await browser.runtime.sendMessage({ type: 'REFRESH_DATA' });
checkIcon.style.setProperty('display', 'block');
spinnerIcon.style.setProperty('display', 'none');
target.removeAttribute('data-animation');
target.removeAttribute('data-refreshing');
updateDatabaseVersion();
window.setTimeout(() => {
checkIcon.style.setProperty('display', 'none');
spinnerIcon.style.setProperty('display', 'block');
target.removeAttribute('disabled');
target.setAttribute('data-animation', 'flip');
}, 5000);
}
/**
@ -160,6 +186,19 @@ function translate() {
}
}
/**
* @async
* @description Update the database version element
* @returns {Promise<void>}
*/
async function updateDatabaseVersion() {
const data = await browser.runtime.sendMessage({ hostname, type: 'GET_DATA' });
const databaseVersionElement = document.getElementById('database-version');
if (data.version) databaseVersionElement.innerText = data.version;
else databaseVersionElement.style.setProperty('display', 'none');
}
/**
* @description Listen to document ready
* @listens document#DOMContentLoaded

View File

@ -110,6 +110,31 @@ popup-data:not(:first-child) {
margin-top: 4px;
}
popup-data-button {
cursor: pointer;
outline: none;
transition: 0.4s;
}
popup-data-button:disabled {
cursor: not-allowed;
}
popup-data-button[data-animation='flip']:focus,
popup-data-button[data-animation='flip']:hover {
transform: rotate(-180deg);
}
popup-data-button[data-refreshing='true'] {
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(-360deg);
}
}
popup-data-container {
font-size: 12px;
grid-column: 1 / -1;
@ -121,6 +146,10 @@ strong {
font-weight: bold;
}
#refresh-database-check {
display: none;
}
#power-option {
color: var(--color-white);
word-break: break-all;