From bb164a87955803cfd0716aba12e42c0e3e9cdfe5 Mon Sep 17 00:00:00 2001 From: Mikhail Korolev Date: Wed, 6 Dec 2023 21:20:27 +0100 Subject: [PATCH] Connect tooltips, text insertion --- src/components/FillSelector.svelte | 38 ++++++++++++++----- src/components/ui/TalkView.svelte | 3 ++ src/content/index.ts | 60 ++++++++++++++++++++++-------- src/tools/helpers.ts | 19 +++++++++- 4 files changed, 94 insertions(+), 26 deletions(-) diff --git a/src/components/FillSelector.svelte b/src/components/FillSelector.svelte index 03251e0..955cb3f 100644 --- a/src/components/FillSelector.svelte +++ b/src/components/FillSelector.svelte @@ -1,21 +1,32 @@
@@ -38,15 +54,17 @@
diff --git a/src/components/ui/TalkView.svelte b/src/components/ui/TalkView.svelte index 4aeeb64..3a0fdd0 100644 --- a/src/components/ui/TalkView.svelte +++ b/src/components/ui/TalkView.svelte @@ -20,6 +20,9 @@ .talk { display: flex; flex-direction: column; + box-shadow: 0px 3px 17px 0px #0000002b; + padding: 0.3rem; + border-radius: 3px; } .talk p { white-space: pre-line; diff --git a/src/content/index.ts b/src/content/index.ts index 104c2a9..58a6a7f 100644 --- a/src/content/index.ts +++ b/src/content/index.ts @@ -1,36 +1,66 @@ import FillSelector from "../components/FillSelector.svelte"; import type {PersonalInfo, Talk} from "../storage"; +import { createPopper } from '@popperjs/core'; +import { writable } from 'svelte/store'; // Content scripts // https://developer.chrome.com/docs/extensions/mv3/content_scripts/ // Some global styles on the page import "./styles.css"; +import {isElementVisible} from "../tools/helpers"; const createTooltip = () => { const tooltip = document.createElement('div') - const container = document.createElement('div') + const target = document.createElement('div') tooltip.id = 'sfp-tooltip' tooltip.innerHTML = `
` - tooltip.append(container) - document.body.prepend(tooltip) + tooltip.append(target) + document.body.append(tooltip) + return { tooltip, target } +} - return container +const drawTooltip = (target: Element, content: HTMLElement) => { + createPopper(target, content, { + placement: 'left', + modifiers: [ + { + name: 'offset', + options: { + offset: [0, 10], + }, + }, + ], + }); } -const init = async () => { - await chrome.runtime.sendMessage({ requestTalk: 'please' }); - chrome.runtime.onMessage.addListener( - async function(request: { targetTalk: Talk, personalInfo: PersonalInfo }, sender, sendResponse) { - const { targetTalk, personalInfo } = request - console.log('Initiating submission process with the following data: ', { targetTalk, personalInfo }) +const onStart = async (request: { targetTalk: Talk, personalInfo: PersonalInfo }) => { + const { targetTalk, personalInfo } = request + console.log('Initiating submission process with the following data: ', { targetTalk, personalInfo }) + + // @TODO: apply more sophisticated form detection method + const formInputs = document.querySelectorAll('input, textarea') + const visibleInputs = Array.from(formInputs).filter(isElementVisible) + + const activeInput = writable(visibleInputs[0]) + + const { target, tooltip } = createTooltip() + new FillSelector({ target, props: { activeTalk: targetTalk, personalInfo, activeInput } }) - const target = createTooltip() - new FillSelector({ target, props: { activeTalk: targetTalk, personalInfo } }) - // @TODO this is where we inject popper - } - ); + drawTooltip(visibleInputs[0], tooltip) + + visibleInputs.forEach(input => { + input.addEventListener('focus', () => { + activeInput.set(input) + drawTooltip(input, tooltip) + }) + }) +} + +const init = async () => { + await chrome.runtime.sendMessage({ requestTalk: 'please' }); + chrome.runtime.onMessage.addListener(onStart); } console.log('I have arrived!') diff --git a/src/tools/helpers.ts b/src/tools/helpers.ts index fdbf25b..561f420 100644 --- a/src/tools/helpers.ts +++ b/src/tools/helpers.ts @@ -1,9 +1,26 @@ import type {Talk} from "../storage"; +export type FocusableTarget = HTMLTextAreaElement | HTMLInputElement + export const HIDDEN_KEYS = ['id', '__revision']; export const getTalkName = (talk: Talk) => { return talk.title || talk.Title || talk.id; } -export const publicKeysOnly = (key: string) => !HIDDEN_KEYS.includes(key); \ No newline at end of file +export const publicKeysOnly = (key: string) => !HIDDEN_KEYS.includes(key); + +export const isElementVisible = (el: Element) => { + const style = window.getComputedStyle(el); + return !((style.display === 'none') || (style.visibility === 'hidden')) +} + +export const simulateInput = (element: FocusableTarget, text: string) => { + element.focus() + element.select() + try { + document.execCommand("insertText", false, text) + } catch (e) { + console.error("is document.execCommand already disabled in your browser? Tough luck.", e); + } +} \ No newline at end of file