yert
parent
39675b5ab6
commit
e927fc1b6f
|
|
@ -0,0 +1,55 @@
|
||||||
|
import { actions, downloads } from '/js/api.js'
|
||||||
|
|
||||||
|
export async function enable() {
|
||||||
|
const actions_container = document.getElementById('actions');
|
||||||
|
const tab2 = document.querySelector("input[type=radio]#tab-2");
|
||||||
|
console.log(tab2);
|
||||||
|
actions_container.innerHTML = "";
|
||||||
|
|
||||||
|
|
||||||
|
async function get_current_tab_url() {
|
||||||
|
return (await browser.tabs.query({ currentWindow: true, active: true }))[0].url
|
||||||
|
}
|
||||||
|
|
||||||
|
const groups = {};
|
||||||
|
|
||||||
|
function get_group(name) {
|
||||||
|
if (!name) name = "Ungrouped";
|
||||||
|
if (name in groups) return groups[name];
|
||||||
|
const fieldset = document.createElement('fieldset');
|
||||||
|
// fieldset.style.background = get_color();
|
||||||
|
const legend = document.createElement('legend');
|
||||||
|
legend.innerText = name;
|
||||||
|
fieldset.className = "actionset";
|
||||||
|
|
||||||
|
fieldset.appendChild(legend);
|
||||||
|
actions_container.appendChild(fieldset);
|
||||||
|
|
||||||
|
groups[name] = fieldset;
|
||||||
|
return groups[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const preset of await actions.get_all()) {
|
||||||
|
const button = document.createElement('button');
|
||||||
|
const fieldset = get_group(preset.folder);
|
||||||
|
fieldset.appendChild(button);
|
||||||
|
|
||||||
|
button.innerText = preset.name;
|
||||||
|
button.addEventListener('click', async function() {
|
||||||
|
const tab_url = await get_current_tab_url()
|
||||||
|
console.log(tab_url, preset.id);
|
||||||
|
downloads.create(tab_url, preset.id);
|
||||||
|
tab2.checked = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const hr = document.createElement('hr');
|
||||||
|
actions_container.appendChild(hr);
|
||||||
|
|
||||||
|
const reload_button = document.createElement('button');
|
||||||
|
reload_button.innerText = "Reload";
|
||||||
|
reload_button.addEventListener('click', enable);
|
||||||
|
actions_container.appendChild(reload_button);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { api_url } from '/js/settings.js';
|
||||||
|
|
||||||
|
const _get = async (route) => {
|
||||||
|
const res = await fetch(await api_url(route));
|
||||||
|
return await res.json();
|
||||||
|
// const mime_type = res.headers.get('content-type').split(";")[0].trim();
|
||||||
|
// if(!mime_type) return;
|
||||||
|
// return
|
||||||
|
};
|
||||||
|
const _post = async (route, data) => await fetch(await api_url(route), {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
body: typeof data === 'string' ? data : JSON.stringify(data)
|
||||||
|
});
|
||||||
|
const _delete = async (route) => await fetch(await api_url(route), { method: 'DELETE' })
|
||||||
|
|
||||||
|
export const actions = {
|
||||||
|
get_all() { return _get('actions') }
|
||||||
|
}
|
||||||
|
|
||||||
|
export const downloads = {
|
||||||
|
create(download_url, preset_id) {
|
||||||
|
return _post('download', {
|
||||||
|
url: download_url,
|
||||||
|
preset_id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const notifications = {
|
||||||
|
get_all() {
|
||||||
|
return _get('notifications');
|
||||||
|
},
|
||||||
|
remove() {
|
||||||
|
return _delete(`notifications/${notification_id}`);
|
||||||
|
},
|
||||||
|
remove_all() {
|
||||||
|
return _delete('notifications/inactive');
|
||||||
|
},
|
||||||
|
get_active() {
|
||||||
|
return _get('notifications/active');
|
||||||
|
},
|
||||||
|
get_failed() {
|
||||||
|
return _get('notifications/failed');
|
||||||
|
},
|
||||||
|
get_succeeded() {
|
||||||
|
return _get('notifications/succeeded');
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,221 @@
|
||||||
|
import { api_url } from '/js/settings.js';
|
||||||
|
import * as api from '/js/api.js';
|
||||||
|
|
||||||
|
function create_notification_element_from_notification_object(notification) {
|
||||||
|
|
||||||
|
const e_container = document.createElement('div');
|
||||||
|
e_container.classList = `status status-${notification.type}`;
|
||||||
|
e_container.setAttribute('notification_id', "" + notification.id);
|
||||||
|
e_container.setAttribute('notification_hash', "" + notification.hash);
|
||||||
|
|
||||||
|
const e_title_span = document.createElement('span');
|
||||||
|
e_title_span.innerText = notification.title;
|
||||||
|
|
||||||
|
const e_title = document.createElement('div');
|
||||||
|
e_title.classList = 'status-title';
|
||||||
|
e_title.appendChild(e_title_span)
|
||||||
|
|
||||||
|
const e_progress = document.createElement('progress');
|
||||||
|
if ('progress' in notification) {
|
||||||
|
if(notification.progress !== null) {
|
||||||
|
e_progress.setAttribute('value', notification.progress);
|
||||||
|
}
|
||||||
|
} else e_progress.style.display = 'none';
|
||||||
|
|
||||||
|
const e_text = document.createElement('div');
|
||||||
|
e_text.classList = 'status-text';
|
||||||
|
e_text.innerHTML = notification.text;
|
||||||
|
|
||||||
|
const e_delete_button = document.createElement('button');
|
||||||
|
e_delete_button.classList = 'dismiss';
|
||||||
|
e_delete_button.innerText = "Dismiss";
|
||||||
|
e_delete_button.addEventListener('click', () => {
|
||||||
|
api.notifications.remove(notification.id);
|
||||||
|
})
|
||||||
|
|
||||||
|
e_container.appendChild(e_title);
|
||||||
|
e_container.appendChild(e_progress);
|
||||||
|
e_container.appendChild(e_text);
|
||||||
|
// e_container.appendChild(e_delete_button);
|
||||||
|
|
||||||
|
return e_container;
|
||||||
|
}
|
||||||
|
|
||||||
|
function begin_status_update_loop() {
|
||||||
|
const statuses_container = document.getElementById('statuses');
|
||||||
|
const clear_button = document.getElementById('clear-notifications-button');
|
||||||
|
const notif_header = document.getElementById('notif-header');
|
||||||
|
|
||||||
|
clear_button.addEventListener('click', () => {
|
||||||
|
api.notifications.remove_all();
|
||||||
|
})
|
||||||
|
|
||||||
|
function get_current_shown_status_ids() {
|
||||||
|
let arr = [];
|
||||||
|
for(const element of statuses_container.children) {
|
||||||
|
arr.push(element.getAttribute("notification_id"))
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function check_statuses() {
|
||||||
|
const active = await api.notifications.get_active();
|
||||||
|
const failed = await api.notifications.get_failed();
|
||||||
|
const succeeded = await api.notifications.get_succeeded();
|
||||||
|
|
||||||
|
notif_header.textContent = `${active.length} Active | ${failed.length} Failed | ${succeeded.length} Succeeded`;
|
||||||
|
|
||||||
|
let req = await fetch(await api_url('notifications'));
|
||||||
|
let json = await req.json();
|
||||||
|
|
||||||
|
const current_status_ids = get_current_shown_status_ids();
|
||||||
|
const new_status_ids = json.map(v => v.id);
|
||||||
|
|
||||||
|
const combined_ids = Array.from(new Set([
|
||||||
|
...current_status_ids,
|
||||||
|
...new_status_ids
|
||||||
|
]));
|
||||||
|
|
||||||
|
const first = new Map(combined_ids.map(notif_id => [
|
||||||
|
notif_id,
|
||||||
|
document.querySelector(`[notification_id="${notif_id}"]`)?.getBoundingClientRect() ?? null
|
||||||
|
]));
|
||||||
|
|
||||||
|
console.log(first);
|
||||||
|
|
||||||
|
for(const status_id of combined_ids) {
|
||||||
|
const in_current = current_status_ids.includes(status_id);
|
||||||
|
const in_new = new_status_ids.includes(status_id);
|
||||||
|
|
||||||
|
if (in_current && !in_new) {
|
||||||
|
const status_element = statuses_container.querySelector(`[notification_id="${status_id}"]`);
|
||||||
|
status_element.outerHTML = "";
|
||||||
|
} else if (!in_current && in_new) {
|
||||||
|
const status_object = json.find(status => status.id === status_id);
|
||||||
|
const new_element = create_notification_element_from_notification_object(status_object)
|
||||||
|
statuses_container.appendChild(new_element);
|
||||||
|
} else if (in_current && in_new) {
|
||||||
|
const status_object = json.find(status => status.id === status_id);
|
||||||
|
const current_element = statuses_container.querySelector(`[notification_id="${status_id}"]`);
|
||||||
|
const new_element = create_notification_element_from_notification_object(status_object);
|
||||||
|
current_element.replaceWith(new_element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new_status_ids.forEach((id, index) => {
|
||||||
|
const el = document.querySelector(`[notification_id="${id}"]`);
|
||||||
|
if (el) el.style.order = index;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
for(const [id, old_rect] of first.entries()) {
|
||||||
|
if(!old_rect) continue;
|
||||||
|
|
||||||
|
const el = document.querySelector(`[notification_id="${id}"]`);
|
||||||
|
if(!el) continue;
|
||||||
|
|
||||||
|
const current_rect = el.getBoundingClientRect();
|
||||||
|
const dy = old_rect.top - current_rect.top;
|
||||||
|
|
||||||
|
el.style.transition = 'none';
|
||||||
|
el.style.transform = `translate(0px, ${dy}px)`;
|
||||||
|
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
el.style.transition = 'transform 300ms ease';
|
||||||
|
el.style.transform = '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// notification_els.forEach(el => {
|
||||||
|
// const prev = first.get(el);
|
||||||
|
// const next = el.getBoundingClientRect();
|
||||||
|
//
|
||||||
|
// const dx = prev.left - next.left;
|
||||||
|
// const dy = prev.top - next.top;
|
||||||
|
//
|
||||||
|
// if (dx === 0 && dy === 0) return;
|
||||||
|
//
|
||||||
|
// el.style.transition = 'none';
|
||||||
|
// el.style.transform = `translate(${dx}px, ${dy}px)`;
|
||||||
|
//
|
||||||
|
// });
|
||||||
|
|
||||||
|
setTimeout(check_statuses, 500);
|
||||||
|
}
|
||||||
|
check_statuses();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function enable() {
|
||||||
|
begin_status_update_loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function alignElements(liveEl, templateEl) {
|
||||||
|
// If node types differ, replace entirely
|
||||||
|
if (liveEl.nodeType !== templateEl.nodeType) {
|
||||||
|
liveEl.replaceWith(templateEl.cloneNode(true));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If element tag names differ, replace
|
||||||
|
if (liveEl.nodeType === Node.ELEMENT_NODE &&
|
||||||
|
liveEl.tagName !== templateEl.tagName) {
|
||||||
|
liveEl.replaceWith(templateEl.cloneNode(true));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text node
|
||||||
|
if (liveEl.nodeType === Node.TEXT_NODE) {
|
||||||
|
if (liveEl.textContent !== templateEl.textContent) {
|
||||||
|
liveEl.textContent = templateEl.textContent;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Element node — sync attributes
|
||||||
|
syncAttributes(liveEl, templateEl);
|
||||||
|
|
||||||
|
// Sync children
|
||||||
|
syncChildren(liveEl, templateEl);
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncAttributes(liveEl, templateEl) {
|
||||||
|
// Remove old attributes
|
||||||
|
for (const attr of [...liveEl.attributes]) {
|
||||||
|
if (!templateEl.hasAttribute(attr.name)) {
|
||||||
|
liveEl.removeAttribute(attr.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add / update attributes
|
||||||
|
for (const attr of [...templateEl.attributes]) {
|
||||||
|
if (liveEl.getAttribute(attr.name) !== attr.value) {
|
||||||
|
liveEl.setAttribute(attr.name, attr.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncChildren(liveEl, templateEl) {
|
||||||
|
const liveChildren = [...liveEl.childNodes];
|
||||||
|
const templateChildren = [...templateEl.childNodes];
|
||||||
|
|
||||||
|
const max = Math.max(liveChildren.length, templateChildren.length);
|
||||||
|
|
||||||
|
for (let i = 0; i < max; i++) {
|
||||||
|
const liveChild = liveChildren[i];
|
||||||
|
const templateChild = templateChildren[i];
|
||||||
|
|
||||||
|
if (!liveChild && templateChild) {
|
||||||
|
liveEl.appendChild(templateChild.cloneNode(true));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (liveChild && !templateChild) {
|
||||||
|
liveChild.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
alignElements(liveChild, templateChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
// const colors = ['red', 'green', 'blue', 'cyan', 'magenta'];
|
||||||
|
// let current_color = -1;
|
||||||
|
// function get_color() { return colors[current_color]; }
|
||||||
|
// function next_color() { current_color ++; current_color = current_color % colors.length };
|
||||||
|
|
||||||
|
import * as settings from '/js/settings.js';
|
||||||
|
import * as notifications from '/js/notifications.js';
|
||||||
|
import * as actions from '/js/actions.js';
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
settings.enable();
|
||||||
|
notifications.enable();
|
||||||
|
actions.enable()
|
||||||
|
// load_domain_from_storage_and_enable_interactions();
|
||||||
|
// arm_action_buttons();
|
||||||
|
// begin_status_update_loop();
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
|
||||||
|
export async function api_url(api_path = "") {
|
||||||
|
const domain = await get_saved_domain();
|
||||||
|
if (!domain) throw Error("No Domain Set");
|
||||||
|
if (api_path.startsWith('/')) api_path = api_path.substring(1);
|
||||||
|
return domain + api_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
const get_saved_domain = async () => (await browser.storage.local.get("domain")).domain;
|
||||||
|
const set_saved_domain = async (domain) => await browser.storage.local.set({ domain });
|
||||||
|
const get_saved_debug = async () => (await browser.storage.local.get("debug")).debug;
|
||||||
|
const set_saved_debug = async (enabled) => await browser.storage.local.set({ debug: enabled });
|
||||||
|
|
||||||
|
function enable_domain_input() {
|
||||||
|
const save_button = document.getElementById("save_domain");
|
||||||
|
const host_input = document.getElementById("host");
|
||||||
|
|
||||||
|
const disable_save_button = () => save_button.setAttribute('disabled', true);
|
||||||
|
const enable_save_button = () => save_button.removeAttribute('disabled');
|
||||||
|
|
||||||
|
async function populate_domain_textbox_from_storage() {
|
||||||
|
const domain = await get_saved_domain()
|
||||||
|
if (!domain) return;
|
||||||
|
host_input.value = domain;
|
||||||
|
disable_save_button();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function domain_input_changed() {
|
||||||
|
const saved_domain = await get_saved_domain();
|
||||||
|
const current_domain = host_input.value;
|
||||||
|
if(saved_domain !== current_domain) enable_save_button();
|
||||||
|
else disable_save_button();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function save_domain_input_to_storage() {
|
||||||
|
if (!host_input.value.endsWith("/"))
|
||||||
|
host_input.value = host_input.value + "/";
|
||||||
|
const saved = set_saved_domain(host_input.value);
|
||||||
|
|
||||||
|
const granted = await browser.permissions.request({
|
||||||
|
origins: [host_input.value]
|
||||||
|
});
|
||||||
|
if (!granted) throw new Error("Permission denied");
|
||||||
|
|
||||||
|
await saved;
|
||||||
|
disable_save_button();
|
||||||
|
}
|
||||||
|
|
||||||
|
populate_domain_textbox_from_storage()
|
||||||
|
host_input.addEventListener('change', domain_input_changed);
|
||||||
|
host_input.addEventListener('keypress', domain_input_changed);
|
||||||
|
host_input.addEventListener('keyup', domain_input_changed);
|
||||||
|
host_input.addEventListener('keydown', domain_input_changed);
|
||||||
|
save_button.addEventListener('click', save_domain_input_to_storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
function enable_debug_toggle() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export function enable() {
|
||||||
|
enable_domain_input();
|
||||||
|
enable_debug_toggle();
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
zip -r -FS downloader.zip \
|
zip -r -FS downloader.zip \
|
||||||
background.js \
|
|
||||||
manifest.json \
|
manifest.json \
|
||||||
popup.html \
|
popup.html \
|
||||||
popup.js
|
js/*
|
||||||
|
|
|
||||||
21
popup.html
21
popup.html
|
|
@ -15,19 +15,23 @@ hr { border: none; border-bottom: 1px solid #CCC; }
|
||||||
body:has(#tab-1:checked) .tab-panel:not(.tab-panel-1) { display: none; }
|
body:has(#tab-1:checked) .tab-panel:not(.tab-panel-1) { display: none; }
|
||||||
body:has(#tab-2:checked) .tab-panel:not(.tab-panel-2) { display: none; }
|
body:has(#tab-2:checked) .tab-panel:not(.tab-panel-2) { display: none; }
|
||||||
body:has(#tab-3:checked) .tab-panel:not(.tab-panel-3) { display: none; }
|
body:has(#tab-3:checked) .tab-panel:not(.tab-panel-3) { display: none; }
|
||||||
|
#statuses { display: flex; flex-direction: column; }
|
||||||
.status {
|
.status {
|
||||||
font-size: 0.8em; border: 1px solid black;
|
font-size: 0.8em; border: 1px solid black;
|
||||||
padding: 8px; border-radius: 8px; overflow: hidden;
|
padding: 8px; border-radius: 8px; overflow: hidden;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
.status .status-title { white-space: nowrap; font-weight: 900; }
|
/* .status .status-title { white-space: nowrap; font-weight: 900; overflow: hidden; } */
|
||||||
|
/* .status .status-title span { display: inline-block; } */
|
||||||
.status-debug { background: #ff8cff }
|
.status-debug { background: #ff8cff }
|
||||||
.status-success { background: #8cff8c }
|
.status-success { background: #8cff8c }
|
||||||
.status-info { background: #b3d9ff }
|
.status-info { background: #b3d9ff }
|
||||||
.status-warning.status-warn { background: #ffff8c }
|
.status-warning, .status-warn { background: #ffff8c }
|
||||||
.status-error { background: #ff8c8c }
|
.status-error { background: #ff8c8c }
|
||||||
|
|
||||||
|
.tab-panel-3 { display: flex; gap: 8px; flex-direction: column; }
|
||||||
|
progress { width: 100%; margin: 0px; }
|
||||||
|
|
||||||
fieldset.actionset { display: flex; flex-direction: column; gap: 6px; }
|
fieldset.actionset { display: flex; flex-direction: column; gap: 6px; }
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
|
|
@ -52,7 +56,10 @@ pre {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-panel tab-panel-2">
|
<div class="tab-panel tab-panel-2">
|
||||||
<pre id="json_dump"></pre>
|
<div style="display: flex; margin-bottom: 8px;">
|
||||||
|
<span id="notif-header" style="flex-grow: 1; font-size: 12px; padding-top: 4px;">1 Active | 2 Failed | 3 Completed</span>
|
||||||
|
<button id="clear-notifications-button">Clear</button>
|
||||||
|
</div>
|
||||||
<div id="statuses"></div>
|
<div id="statuses"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -61,8 +68,12 @@ pre {
|
||||||
<input style="flex-grow: 1;" id="host" placeholder="Downloader Domain" />
|
<input style="flex-grow: 1;" id="host" placeholder="Downloader Domain" />
|
||||||
<button id="save_domain">Save</button>
|
<button id="save_domain">Save</button>
|
||||||
</div>
|
</div>
|
||||||
|
<label for="debug-checkbox">
|
||||||
|
<input type="checkbox" id="debug-checkbox"></input>
|
||||||
|
Enable Debug Mode
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="popup.js"></script>
|
<script type="module" src="/js/popup.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
206
popup.js
206
popup.js
|
|
@ -1,206 +0,0 @@
|
||||||
const get_saved_domain = async () => (await browser.storage.local.get("domain")).domain;
|
|
||||||
const set_saved_domain = async (domain) => await browser.storage.local.set({ domain });
|
|
||||||
|
|
||||||
function load_domain_from_storage_and_enable_interactions() {
|
|
||||||
const save_button = document.getElementById("save_domain");
|
|
||||||
const host_input = document.getElementById("host");
|
|
||||||
|
|
||||||
const disable_save_button = () => save_button.setAttribute('disabled', true);
|
|
||||||
const enable_save_button = () => save_button.removeAttribute('disabled');
|
|
||||||
|
|
||||||
async function populate_domain_textbox_from_storage() {
|
|
||||||
const domain = await get_saved_domain()
|
|
||||||
if (!domain) return;
|
|
||||||
host_input.value = domain;
|
|
||||||
disable_save_button();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function domain_input_changed() {
|
|
||||||
const saved_domain = await get_saved_domain();
|
|
||||||
const current_domain = host_input.value;
|
|
||||||
if(saved_domain !== current_domain) enable_save_button();
|
|
||||||
else disable_save_button();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function save_domain_input_to_storage() {
|
|
||||||
if (!host_input.value.endsWith("/"))
|
|
||||||
host_input.value = host_input.value + "/";
|
|
||||||
const saved = set_saved_domain(host_input.value);
|
|
||||||
|
|
||||||
const granted = await browser.permissions.request({
|
|
||||||
origins: [host_input.value]
|
|
||||||
});
|
|
||||||
if (!granted) throw new Error("Permission denied");
|
|
||||||
|
|
||||||
await saved;
|
|
||||||
disable_save_button();
|
|
||||||
}
|
|
||||||
|
|
||||||
populate_domain_textbox_from_storage()
|
|
||||||
host_input.addEventListener('change', domain_input_changed);
|
|
||||||
host_input.addEventListener('keypress', domain_input_changed);
|
|
||||||
host_input.addEventListener('keyup', domain_input_changed);
|
|
||||||
host_input.addEventListener('keydown', domain_input_changed);
|
|
||||||
save_button.addEventListener('click', save_domain_input_to_storage);
|
|
||||||
}
|
|
||||||
|
|
||||||
const colors = ['red', 'green', 'blue', 'cyan', 'magenta'];
|
|
||||||
let current_color = -1;
|
|
||||||
function get_color() { return colors[current_color]; }
|
|
||||||
function next_color() { current_color ++; current_color = current_color % colors.length };
|
|
||||||
|
|
||||||
async function arm_action_buttons() {
|
|
||||||
next_color();
|
|
||||||
const actions_container = document.getElementById('actions');
|
|
||||||
actions_container.innerHTML = "";
|
|
||||||
|
|
||||||
async function send_data(route, payload) {
|
|
||||||
const domain = (await get_saved_domain()) + route;
|
|
||||||
await browser.runtime.sendMessage({
|
|
||||||
type: 'send',
|
|
||||||
host: domain,
|
|
||||||
data: JSON.stringify(payload)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function get_current_tab_url() {
|
|
||||||
return (await browser.tabs.query({ currentWindow: true, active: true }))[0].url
|
|
||||||
}
|
|
||||||
|
|
||||||
const presets_req = await fetch(await get_saved_domain() + 'download/presets');
|
|
||||||
const presets = await presets_req.json();
|
|
||||||
|
|
||||||
const groups = {};
|
|
||||||
|
|
||||||
function get_group(name) {
|
|
||||||
if (!name) name = "Ungrouped";
|
|
||||||
if (name in groups) return groups[name];
|
|
||||||
const fieldset = document.createElement('fieldset');
|
|
||||||
// fieldset.style.background = get_color();
|
|
||||||
const legend = document.createElement('legend');
|
|
||||||
legend.innerText = name;
|
|
||||||
fieldset.className = "actionset";
|
|
||||||
|
|
||||||
fieldset.appendChild(legend);
|
|
||||||
actions_container.appendChild(fieldset);
|
|
||||||
|
|
||||||
groups[name] = fieldset;
|
|
||||||
return groups[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const preset of presets) {
|
|
||||||
const button = document.createElement('button');
|
|
||||||
const fieldset = get_group(preset.folder);
|
|
||||||
fieldset.appendChild(button);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
button.innerText = preset.name;
|
|
||||||
button.addEventListener('click', async function() {
|
|
||||||
send_data('download', {
|
|
||||||
url: await get_current_tab_url(),
|
|
||||||
preset_id: preset.id,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const hr = document.createElement('hr');
|
|
||||||
actions_container.appendChild(hr);
|
|
||||||
|
|
||||||
const reload_button = document.createElement('button');
|
|
||||||
reload_button.innerText = "Reload";
|
|
||||||
reload_button.addEventListener('click', arm_action_buttons);
|
|
||||||
actions_container.appendChild(reload_button);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
async function dismiss_notif(status_id) {
|
|
||||||
url = await get_saved_domain() + 'notification/' + status_id
|
|
||||||
fetch(url, {
|
|
||||||
method: 'DELETE'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function create_notification_element_from_notification_object(notification) {
|
|
||||||
|
|
||||||
const e_container = document.createElement('div');
|
|
||||||
e_container.classList = `status status-${notification.type}`;
|
|
||||||
e_container.setAttribute('notification_id', "" + notification.id);
|
|
||||||
e_container.setAttribute('notification_hash', "" + notification.hash);
|
|
||||||
|
|
||||||
const e_title = document.createElement('div');
|
|
||||||
e_title.classList = 'status-title';
|
|
||||||
e_title.innerText = notification.title;
|
|
||||||
|
|
||||||
const e_text = document.createElement('div');
|
|
||||||
e_text.classList = 'status-text';
|
|
||||||
e_text.innerHTML = notification.text;
|
|
||||||
|
|
||||||
const e_delete_button = document.createElement('button');
|
|
||||||
e_delete_button.classList = 'dismiss';
|
|
||||||
e_delete_button.innerText = "Dismis";
|
|
||||||
e_delete_button.addEventListener('click', () => {
|
|
||||||
dismiss_notif(notification.id);
|
|
||||||
})
|
|
||||||
|
|
||||||
e_container.appendChild(e_title);
|
|
||||||
e_container.appendChild(e_text);
|
|
||||||
e_container.appendChild(e_delete_button);
|
|
||||||
|
|
||||||
return e_container;
|
|
||||||
}
|
|
||||||
|
|
||||||
function begin_status_update_loop() {
|
|
||||||
const statuses_container = document.getElementById('statuses');
|
|
||||||
|
|
||||||
function get_current_shown_status_ids() {
|
|
||||||
let arr = [];
|
|
||||||
for(const element of statuses_container.children) {
|
|
||||||
arr.push(element.getAttribute("notification_id"))
|
|
||||||
}
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function check_statuses() {
|
|
||||||
let domain = await get_saved_domain();
|
|
||||||
let req = await fetch(domain + 'notifications');
|
|
||||||
let json = await req.json();
|
|
||||||
|
|
||||||
const current_status_ids = get_current_shown_status_ids();
|
|
||||||
const new_status_ids = json.map(v => v.id);
|
|
||||||
|
|
||||||
const combined_ids = Array.from(new Set([
|
|
||||||
...current_status_ids,
|
|
||||||
...new_status_ids
|
|
||||||
]));
|
|
||||||
|
|
||||||
for(const status_id of combined_ids) {
|
|
||||||
const in_current = current_status_ids.includes(status_id);
|
|
||||||
const in_new = new_status_ids.includes(status_id);
|
|
||||||
|
|
||||||
if (in_current && !in_new) {
|
|
||||||
const status_element = statuses_container.querySelector(`[notification_id="${status_id}"]`);
|
|
||||||
status_element.outerHTML = "";
|
|
||||||
} else if (!in_current && in_new) {
|
|
||||||
const status_object = json.find(status => status.id === status_id);
|
|
||||||
const new_element = create_notification_element_from_notification_object(status_object)
|
|
||||||
statuses_container.appendChild(new_element);
|
|
||||||
} else if (in_current && in_new) {
|
|
||||||
const status_object = json.find(status => status.id === status_id);
|
|
||||||
const current_element = statuses_container.querySelector(`[notification_id="${status_id}"]`);
|
|
||||||
const new_element = create_notification_element_from_notification_object(status_object);
|
|
||||||
current_element.replaceWith(new_element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(check_statuses, 500);
|
|
||||||
}
|
|
||||||
check_statuses();
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
load_domain_from_storage_and_enable_interactions();
|
|
||||||
arm_action_buttons();
|
|
||||||
begin_status_update_loop();
|
|
||||||
});
|
|
||||||
Loading…
Reference in New Issue