diff --git a/force_delete.css b/force_delete.css new file mode 100644 index 0000000..9c887ca --- /dev/null +++ b/force_delete.css @@ -0,0 +1,9 @@ +.__force_deleted { + animation: __force_deleted 0.2s ease-out; +} + +@keyframes __force_deleted { + 0% { scale: inherit } + 50% { scale: 1.1 } + 100% { scale: inherit } +} diff --git a/force_delete.ts b/force_delete.ts index 5a61e88..21757df 100644 --- a/force_delete.ts +++ b/force_delete.ts @@ -1,5 +1,5 @@ class ForceDeleteExtension { - private readonly LOOP_INTERVAL_TIME = 500 + private readonly LOOP_INTERVAL_TIME = 100 private readonly EXPLICIT_TARGET_SELECTORS = [ @@ -11,7 +11,11 @@ class ForceDeleteExtension { // IAM --- 'div[data-testid="roles-delete-modal-input"]>input', - 'div[data-testid="policies-delete-modal-input"]>input' + 'div[data-testid="policies-delete-modal-input"]>input', + 'div[data-testid="policies-from-role-delete-modal-input"]>input', + + // Firehose --- + 'div[data-hook="DELETE_CONFIRMATION_INPUT"]>input' ] @@ -73,6 +77,8 @@ class ForceDeleteExtension { elements.forEach(this.applyDeleteMessage.bind(this)) private readonly applyDeleteMessage = (element: HTMLInputElement): void => { + element.classList.add('__force_deleted') + element.value = element.placeholder element.dispatchEvent(new Event('input', { bubbles: true diff --git a/form_saver.ts b/form_saver.ts deleted file mode 100644 index 9b41079..0000000 --- a/form_saver.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { CommunicateMessage, FormSavedDataContent } from './types' - -class FormSaverExtension { - private readonly api = browser ?? chrome - - public startListen = (): void => - this.api.runtime.onMessage.addListener(this.messageHandler.bind(this)) - - // --- - - private readonly messageHandler = (message: unknown, _: any, sendResponse: (message: CommunicateMessage) => void): undefined => { - const receivedMessage = message as CommunicateMessage - - if (receivedMessage.type === 'SAVE_FORM') { - return sendResponse(this.saveForm()) as undefined - } - - if (receivedMessage.type === 'LOAD_FORM') { - return this.loadForm(receivedMessage.data?.contents ?? []) as undefined - } - } - - private readonly saveForm = (): CommunicateMessage => { - const inputElements = this.findInputElements() - - return { - type: 'FORM_SAVED', - data: { - url: window.location.href, - contents: [ - ...this.retrieveTextInputValues(inputElements) - ] - } - } - } - - private readonly loadForm = (formSaved: FormSavedDataContent[]): void => { - this.loadTextInputValues(formSaved) - } - - // --- - - private readonly findInputElements = (): HTMLInputElement[] => - [...document.querySelectorAll('input')] - - private readonly retrieveTextInputValues = (elements: HTMLInputElement[]): FormSavedDataContent[] => - elements - .filter((v) => v.type === 'text') - .map((v) => ({ - selector: `div#${v.parentElement?.id ?? ''}>input`, - type: 'TEXT' as const, - value: v.value - })) - - // --- - - private readonly loadTextInputValues = (formSaved: FormSavedDataContent[]): void => - formSaved - .filter((v) => v.type === 'TEXT') - .forEach(this.loadTextInputValue.bind(this)) - - private readonly loadTextInputValue = (formSaved: FormSavedDataContent): void => { - const element = document.querySelector(formSaved.selector) - if (element === null || !(element instanceof HTMLInputElement) || element.type !== 'text') { return } - - element.value = formSaved.value - element.dispatchEvent(new Event('input', { - bubbles: true - })) - } -} - -new FormSaverExtension() - .startListen() diff --git a/manifest.json b/manifest.json index 70175cd..6c4d0c7 100644 --- a/manifest.json +++ b/manifest.json @@ -9,23 +9,14 @@ "48": "icons/koishi.webp" }, - "action": { - "default_icon": "icons/koishi.webp", - "default_title": "Koishi", - "default_popup": "popup/index.html" - }, - - "host_permissions": [ - "*://*.console.aws.amazon.com/*" - ], - - "content_scripts": [ { "matches": ["*://*.console.aws.amazon.com/*"], "js": [ - "force_delete.js", - "form_saver.js" + "force_delete.js" + ], + "css": [ + "force_delete.css" ], "all_frames": true, "match_about_blank": true, diff --git a/popup/index.html b/popup/index.html deleted file mode 100644 index b87d858..0000000 --- a/popup/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - Koishi Form Saver - - - -

Form Saver

- - - - - - - - - - - - -
#urlcontentaction
- - - - - diff --git a/popup/main.css b/popup/main.css deleted file mode 100644 index 31a2249..0000000 --- a/popup/main.css +++ /dev/null @@ -1,34 +0,0 @@ -:root { - background-color: #212121; - color: #fafafa; - - font-family: Arial, Helvetica, sans-serif; -} - -body { - padding: 10px; -} - -* { - padding: 0; - margin: 0; - font-size: 14px; -} - -table { - user-select: none; -} - -button { - background-color: #626262; - padding: 2px 5px; - color: #fafafa; - border: none; - outline: 1px solid #af7d85; - border-radius: 6px; - cursor: pointer; -} - -button:hover { - background-color: #838383; -} diff --git a/popup/main.ts b/popup/main.ts deleted file mode 100644 index c182541..0000000 --- a/popup/main.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { CommunicateMessage, FormSavedData } from '../types' - -void (async () => { - const api = browser ?? chrome - - const [tab] = await api.tabs.query({ - active: true, - currentWindow: true - }) - - if (tab.url === undefined) { - document.body.innerText = 'Extension disabled on this page' - return - } - - if (localStorage.getItem('form_saved') === null) { localStorage.setItem('form_saved', '[]') } - - document.getElementById('save')?.addEventListener('click', () => { - void (async () => { - const formSaved: CommunicateMessage = await api.tabs.sendMessage(tab.id ?? 0, { - type: 'SAVE_FORM' - }) - - if (formSaved.type !== 'FORM_SAVED') { return } - - const prevSaved = JSON.parse(localStorage.getItem('form_saved') ?? '') as Array - const newSaved = JSON.stringify([ - { - id: crypto.randomUUID(), - ...formSaved.data - }, - ...prevSaved.slice(0, 10) - ]) - - localStorage.setItem('form_saved', newSaved) - - renderTable() - })() - }) - - renderTable() - function renderTable (): void { - const formSaved = JSON.parse(localStorage.getItem('form_saved') ?? '') as Array - const renderPoint = document.getElementById('render_point') - - if (renderPoint === null) { - return - } - - renderPoint.innerHTML = '' - - for (const form of formSaved) { - renderPoint.innerHTML += ` - - ${form.id.substring(0, 8)} - ${new URL(form.url).pathname}${new URL(form.url).hash} - ${form.contents.filter((v) => v.type === 'TEXT').length} Texts - - - - - - ` - } - - for (const form of formSaved) { - document.getElementById(`load-${form.id}`)?.addEventListener('click', () => { - void api.tabs.sendMessage(tab.id ?? 0, { - type: 'LOAD_FORM', - data: form - }) - }) - - document.getElementById(`delete-${form.id}`)?.addEventListener('click', () => { - const prevSaved = JSON.parse(localStorage.getItem('form_saved') ?? '') as Array - const newSaved = JSON.stringify(prevSaved.filter((v) => v.id !== form.id)) - - localStorage.setItem('form_saved', newSaved) - renderTable() - }) - } - } -})()