diff --git a/src/plugins/monofile.ts b/src/plugins/monofile.ts index 1ca42ad6..da121511 100644 --- a/src/plugins/monofile.ts +++ b/src/plugins/monofile.ts @@ -465,8 +465,6 @@ export function tryLoad() { ) } - - function ReplaceMenuSVG(element: HTMLElement, svg: string) { let item = element.firstChild as HTMLElement item!.firstChild!.remove() @@ -477,10 +475,11 @@ function ReplaceMenuSVG(element: HTMLElement, svg: string) { item.insertBefore(newsvg as Node, item.firstChild) } +const processedSymbol = Symbol('processed') + export async function ObserveMenuItemPosition() { await waitForElm("#menu > ul > li") - await delay(100) - + eventManager.register( "menuList", { @@ -488,6 +487,19 @@ export async function ObserveMenuItemPosition() { }, (element: Element) => { const node = element as HTMLElement + + // Only process top-level menu items and skip everything else + if (!node.classList.contains('item') || + node.nodeName !== 'LI' || + node.parentElement?.parentElement?.id !== 'menu') { + return + } + + // Early exit if already processed + if ((element as any)[processedSymbol]) { + return + } + if (!node?.dataset?.checked && !MenuOptionsOpen) { const key = MenuitemSVGKey[node?.dataset?.key! as keyof typeof MenuitemSVGKey] @@ -511,7 +523,9 @@ export async function ObserveMenuItemPosition() { label.replaceChild(span, textNode) } } - ChangeMenuItemPositions(settingsState.menuorder) + ChangeMenuItemPositions(settingsState.menuorder); + + (element as any)[processedSymbol] = true } }, ) @@ -584,9 +598,10 @@ export function init() { if (settingsState.onoff) { console.info("[BetterSEQTA+] Enabled") - if (settingsState.DarkMode) document.documentElement.classList.add("dark") + if (settingsState.DarkMode) document.documentElement.classList.add("dark"); document.querySelector(".legacy-root")?.classList.add("hidden") + ObserveMenuItemPosition(); new StorageChangeHandler() new MessageHandler() diff --git a/src/seqta/utils/Openers/OpenMenuOptions.ts b/src/seqta/utils/Openers/OpenMenuOptions.ts index 40dd20f4..bcef5bc8 100644 --- a/src/seqta/utils/Openers/OpenMenuOptions.ts +++ b/src/seqta/utils/Openers/OpenMenuOptions.ts @@ -1,4 +1,5 @@ +import type { SettingsState } from "@/types/storage" import { settingsState } from "../listeners/SettingsState" import stringToHTML from "../stringToHTML" import Sortable from "sortablejs" @@ -7,250 +8,252 @@ export let MenuOptionsOpen = false export function OpenMenuOptions() { - var container = document.getElementById("container") - var menu = document.getElementById("menu") - - if (settingsState.defaultmenuorder.length == 0) { - let childnodes = menu!.firstChild!.childNodes - let newdefaultmenuorder = [] - for (let i = 0; i < childnodes.length; i++) { - const element = childnodes[i] + var container = document.getElementById("container") + var menu = document.getElementById("menu") + + if (settingsState.defaultmenuorder.length == 0) { + let childnodes = menu!.firstChild!.childNodes + let newdefaultmenuorder = [] + for (let i = 0; i < childnodes.length; i++) { + const element = childnodes[i] + newdefaultmenuorder.push((element as HTMLElement).dataset.key) + settingsState.defaultmenuorder = newdefaultmenuorder + } + } + let childnodes = menu!.firstChild!.childNodes + if (settingsState.defaultmenuorder.length != childnodes.length) { + for (let i = 0; i < childnodes.length; i++) { + const element = childnodes[i] + if ( + !settingsState.defaultmenuorder.indexOf( + (element as HTMLElement).dataset.key, + ) + ) { + let newdefaultmenuorder = settingsState.defaultmenuorder newdefaultmenuorder.push((element as HTMLElement).dataset.key) settingsState.defaultmenuorder = newdefaultmenuorder } } - let childnodes = menu!.firstChild!.childNodes - if (settingsState.defaultmenuorder.length != childnodes.length) { - for (let i = 0; i < childnodes.length; i++) { - const element = childnodes[i] - if ( - !settingsState.defaultmenuorder.indexOf( - (element as HTMLElement).dataset.key, - ) - ) { - let newdefaultmenuorder = settingsState.defaultmenuorder - newdefaultmenuorder.push((element as HTMLElement).dataset.key) - settingsState.defaultmenuorder = newdefaultmenuorder - } - } + } + + MenuOptionsOpen = true + + var cover = document.createElement("div") + cover.classList.add("notMenuCover") + menu!.style.zIndex = "20" + menu!.style.setProperty("--menuHidden", "flex") + container!.append(cover) + + var menusettings = document.createElement("div") + menusettings.classList.add("editmenuoption-container") + + var defaultbutton = document.createElement("div") + defaultbutton.classList.add("editmenuoption") + defaultbutton.innerText = "Restore Default" + defaultbutton.id = "restoredefaultoption" + + var savebutton = document.createElement("div") + savebutton.classList.add("editmenuoption") + savebutton.innerText = "Save" + savebutton.id = "restoredefaultoption" + + menusettings.appendChild(defaultbutton) + menusettings.appendChild(savebutton) + + menu!.appendChild(menusettings) + + var ListItems = menu!.firstChild!.childNodes + for (let i = 0; i < ListItems.length; i++) { + const element1 = ListItems[i] + const element = element1 as HTMLElement + + ;(element as HTMLElement).classList.add("draggable") + if ((element as HTMLElement).classList.contains("hasChildren")) { + (element as HTMLElement).classList.remove("active") + ;(element.firstChild as HTMLElement).classList.remove("noscroll") } - - MenuOptionsOpen = true - - var cover = document.createElement("div") - cover.classList.add("notMenuCover") - menu!.style.zIndex = "20" - menu!.style.setProperty("--menuHidden", "flex") - container!.append(cover) - - var menusettings = document.createElement("div") - menusettings.classList.add("editmenuoption-container") - - var defaultbutton = document.createElement("div") - defaultbutton.classList.add("editmenuoption") - defaultbutton.innerText = "Restore Default" - defaultbutton.id = "restoredefaultoption" - - var savebutton = document.createElement("div") - savebutton.classList.add("editmenuoption") - savebutton.innerText = "Save" - savebutton.id = "restoredefaultoption" - - menusettings.appendChild(defaultbutton) - menusettings.appendChild(savebutton) - - menu!.appendChild(menusettings) - - var ListItems = menu!.firstChild!.childNodes + + let MenuItemToggle = stringToHTML( + `
`, + ).firstChild + ;(element as HTMLElement).append(MenuItemToggle!) + + if (!element.dataset.betterseqta) { + const a = document.createElement("section") + a.innerHTML = element.innerHTML + cloneAttributes(a, element) + menu!.firstChild!.insertBefore(a, element) + element.remove() + } + } + + if (Object.keys(settingsState.menuitems).length == 0) { + menubuttons = menu!.firstChild!.childNodes + let menuItems = {} as any + for (var i = 0; i < menubuttons.length; i++) { + var id = (menubuttons[i] as HTMLElement).dataset.key + const element: any = {} + element.toggle = true + ;(menuItems[id as keyof typeof menuItems] as any) = element + } + settingsState.menuitems = menuItems + } + + var menubuttons: any = document.getElementsByClassName("menuitem") + + let menuItems = settingsState.menuitems as any + let buttons = document.getElementsByClassName("menuitem") + for (let i = 0; i < buttons.length; i++) { + let id = buttons[i].id as string | undefined + if (menuItems[id as keyof typeof menuItems]) { + (buttons[i] as HTMLInputElement).checked = + menuItems[id as keyof typeof menuItems].toggle + } else { + (buttons[i] as HTMLInputElement).checked = true + } + (buttons[i] as HTMLInputElement).checked = true + } + + try { + var el = document.querySelector("#menu > ul") + var sortable = Sortable.create(el as HTMLElement, { + draggable: ".draggable", + dataIdAttr: "data-key", + animation: 150, + easing: "cubic-bezier(.5,0,.5,1)", + onEnd: function () { + saveNewOrder(sortable) + }, + }) + } catch (err) { + console.error(err) + } + + function changeDisplayProperty(element: any) { + if (!element.checked) { + element.parentNode.parentNode.style.display = "var(--menuHidden)" + } + if (element.checked) { + element.parentNode.parentNode.style.setProperty( + "display", + "flex", + "important", + ) + } + } + + function StoreMenuSettings() { + let menu = document.getElementById("menu") + const menuItems: any = {} + let menubuttons = menu!.firstChild!.childNodes + const button = document.getElementsByClassName("menuitem") + for (let i = 0; i < menubuttons.length; i++) { + const id = (menubuttons[i] as HTMLElement).dataset.key + const element: any = {} + element.toggle = (button[i] as HTMLInputElement).checked + + menuItems[id as keyof typeof menuItems] = element + } + settingsState.menuitems = menuItems + } + + for (let i = 0; i < menubuttons.length; i++) { + const element = menubuttons[i] + element.addEventListener("change", () => { + element.parentElement.parentElement.getAttribute("data-key") + StoreMenuSettings() + changeDisplayProperty(element) + }) + } + + function closeAll() { + menusettings?.remove() + cover?.remove() + MenuOptionsOpen = false + menu!.style.setProperty("--menuHidden", "none") + for (let i = 0; i < ListItems.length; i++) { const element1 = ListItems[i] const element = element1 as HTMLElement - - ;(element as HTMLElement).classList.add("draggable") - if ((element as HTMLElement).classList.contains("hasChildren")) { - (element as HTMLElement).classList.remove("active") - ;(element.firstChild as HTMLElement).classList.remove("noscroll") - } - - let MenuItemToggle = stringToHTML( - `
`, - ).firstChild - ;(element as HTMLElement).append(MenuItemToggle!) - + element.classList.remove("draggable") + element.setAttribute("draggable", "false") + if (!element.dataset.betterseqta) { - const a = document.createElement("section") + const a = document.createElement("li") a.innerHTML = element.innerHTML cloneAttributes(a, element) menu!.firstChild!.insertBefore(a, element) element.remove() } } - - if (Object.keys(settingsState.menuitems).length == 0) { - menubuttons = menu!.firstChild!.childNodes - let menuItems = {} as any - for (var i = 0; i < menubuttons.length; i++) { - var id = (menubuttons[i] as HTMLElement).dataset.key - const element: any = {} - element.toggle = true - ;(menuItems[id as keyof typeof menuItems] as any) = element - } - settingsState.menuitems = menuItems + + let switches = menu!.querySelectorAll(".onoffswitch") + for (let i = 0; i < switches.length; i++) { + switches[i].remove() } - - var menubuttons: any = document.getElementsByClassName("menuitem") - - let menuItems = settingsState.menuitems as any - let buttons = document.getElementsByClassName("menuitem") - for (let i = 0; i < buttons.length; i++) { - let id = buttons[i].id as string | undefined - if (menuItems[id as keyof typeof menuItems]) { - (buttons[i] as HTMLInputElement).checked = - menuItems[id as keyof typeof menuItems].toggle - } else { - (buttons[i] as HTMLInputElement).checked = true - } - (buttons[i] as HTMLInputElement).checked = true - } - - try { - var el = document.querySelector("#menu > ul") - var sortable = Sortable.create(el as HTMLElement, { - draggable: ".draggable", - dataIdAttr: "data-key", - animation: 150, - easing: "cubic-bezier(.5,0,.5,1)", - onEnd: function () { - saveNewOrder(sortable) - }, - }) - } catch (err) { - console.error(err) - } - - function changeDisplayProperty(element: any) { - if (!element.checked) { - element.parentNode.parentNode.style.display = "var(--menuHidden)" - } - if (element.checked) { - element.parentNode.parentNode.style.setProperty( - "display", - "flex", - "important", - ) - } - } - - function StoreMenuSettings() { - let menu = document.getElementById("menu") - const menuItems: any = {} - let menubuttons = menu!.firstChild!.childNodes - const button = document.getElementsByClassName("menuitem") - for (let i = 0; i < menubuttons.length; i++) { - const id = (menubuttons[i] as HTMLElement).dataset.key - const element: any = {} - element.toggle = (button[i] as HTMLInputElement).checked - - menuItems[id as keyof typeof menuItems] = element - } - settingsState.menuitems = menuItems - } - - for (let i = 0; i < menubuttons.length; i++) { - const element = menubuttons[i] - element.addEventListener("change", () => { - element.parentElement.parentElement.getAttribute("data-key") - StoreMenuSettings() - changeDisplayProperty(element) - }) - } - - function closeAll() { - menusettings?.remove() - cover?.remove() - MenuOptionsOpen = false - menu!.style.setProperty("--menuHidden", "none") - - for (let i = 0; i < ListItems.length; i++) { - const element1 = ListItems[i] - const element = element1 as HTMLElement - element.classList.remove("draggable") - element.setAttribute("draggable", "false") - - if (!element.dataset.betterseqta) { - const a = document.createElement("li") - a.innerHTML = element.innerHTML - cloneAttributes(a, element) - menu!.firstChild!.insertBefore(a, element) - element.remove() - } - } - - let switches = menu!.querySelectorAll(".onoffswitch") - for (let i = 0; i < switches.length; i++) { - switches[i].remove() - } - } - - cover?.addEventListener("click", closeAll) - savebutton?.addEventListener("click", closeAll) - - defaultbutton?.addEventListener("click", function () { - const options = settingsState.defaultmenuorder - settingsState.menuorder = options - - ChangeMenuItemPositions(options) - - for (let i = 0; i < menubuttons.length; i++) { - const element = menubuttons[i] - element.checked = true - element.parentNode.parentNode.style.setProperty( - "display", - "flex", - "important", - ) - } - saveNewOrder(sortable) - }) - } - - function saveNewOrder(sortable: any) { - var order = sortable.toArray() - settingsState.menuorder = order - } - - function cloneAttributes(target: any, source: any) { - [...source.attributes].forEach((attr) => { - target.setAttribute(attr.nodeName, attr.nodeValue) - }) } - export function ChangeMenuItemPositions(storage: any) { - let menuorder = storage - - var menuList = document.querySelector("#menu")!.firstChild!.childNodes - - let listorder = [] - for (let i = 0; i < menuList.length; i++) { - const menu = menuList[i] as HTMLElement - - let a = menuorder.indexOf(menu.dataset.key) - - listorder.push(a) + cover?.addEventListener("click", closeAll) + savebutton?.addEventListener("click", closeAll) + + defaultbutton?.addEventListener("click", function () { + const options = settingsState.defaultmenuorder + settingsState.menuorder = options + + ChangeMenuItemPositions(options) + + for (let i = 0; i < menubuttons.length; i++) { + const element = menubuttons[i] + element.checked = true + element.parentNode.parentNode.style.setProperty( + "display", + "flex", + "important", + ) } - - var newArr = [] - for (var i = 0; i < listorder.length; i++) { - newArr[listorder[i]] = menuList[i] + saveNewOrder(sortable) + }) +} + + + +function saveNewOrder(sortable: any) { + var order = sortable.toArray() + settingsState.menuorder = order +} + +function cloneAttributes(target: any, source: any) { + [...source.attributes].forEach((attr) => { + target.setAttribute(attr.nodeName, attr.nodeValue) + }) +} + + + +export function ChangeMenuItemPositions(menuorder: SettingsState["menuorder"]) { + var menuList = document.querySelector("#menu")!.firstChild!.childNodes + + let listorder = [] + for (let i = 0; i < menuList.length; i++) { + const menu = menuList[i] as HTMLElement + + let a = menuorder.indexOf(menu.dataset.key) + + listorder.push(a) + } + + var newArr = [] + for (var i = 0; i < listorder.length; i++) { + newArr[listorder[i]] = menuList[i] + } + + let listItemsDOM = document.getElementById("menu")!.firstChild + for (let i = 0; i < newArr.length; i++) { + const element = newArr[i] + if (element) { + const elem = element as HTMLElement + elem.setAttribute("data-checked", "true") + listItemsDOM!.appendChild(element) } - - let listItemsDOM = document.getElementById("menu")!.firstChild - for (let i = 0; i < newArr.length; i++) { - const element = newArr[i] - if (element) { - const elem = element as HTMLElement - elem.setAttribute("data-checked", "true") - listItemsDOM!.appendChild(element) - } - } - } \ No newline at end of file + } +} \ No newline at end of file diff --git a/src/seqta/utils/Whatsnew.ts b/src/seqta/utils/Whatsnew.ts index e659dcb3..86a16f59 100644 --- a/src/seqta/utils/Whatsnew.ts +++ b/src/seqta/utils/Whatsnew.ts @@ -2,7 +2,7 @@ import { settingsState } from "./listeners/SettingsState" import { animate, stagger } from "motion" import stringToHTML from "./stringToHTML" import browser from "webextension-polyfill" -import kofi from "@/resources/kofi.png" +import kofi from "@/resources/kofi.png?base64" export async function DeleteWhatsNew() { const bkelement = document.getElementById("whatsnewbk") diff --git a/src/seqta/utils/listeners/MessageListener.ts b/src/seqta/utils/listeners/MessageListener.ts index 673ca435..ac791882 100644 --- a/src/seqta/utils/listeners/MessageListener.ts +++ b/src/seqta/utils/listeners/MessageListener.ts @@ -108,7 +108,6 @@ export class MessageHandler { editSidebar() { if (!MenuOptionsOpen) { OpenMenuOptions(); - closeExtensionPopup(); } } } \ No newline at end of file