Skip to content

Commit

Permalink
refactor: dom components
Browse files Browse the repository at this point in the history
  • Loading branch information
rpidanny committed May 7, 2023
1 parent 69295f0 commit 56e20e3
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 47 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import { templates } from './templates';

const CLASS_SELECTED = 'bg-gray-200';
const CLASS_OPTIONS = [
'p-2',
'cursor-pointer',
'hover:bg-gray-200',
'dark:hover:bg-gray-800',
];
const SELECTOR_TEXTAREA = 'div.relative > textarea';

export class ChatGPTDom {
export abstract class BaseDom {
protected abstract name: string;
protected abstract textAreaSelector: string;
protected abstract templateClasses: string[];
protected abstract selectedClassName: string;

selectedIndex = -1;
textArea!: HTMLTextAreaElement;
templatesList!: HTMLUListElement;
Expand All @@ -19,23 +15,26 @@ export class ChatGPTDom {
this.init = this.init.bind(this);
}

protected abstract setText(text: string): void;

async init() {
console.log('Initializing ChatGPT DOM');
await this.getTextArea();
await this.addTemplates();
console.log(`Initializing ${this.name} DOM`);
this.textArea = await this.getTextArea();
this.templatesList = await this.addTemplates();
await this.addEventListeners();
}

private async getTextArea(): Promise<void> {
const textArea =
document.querySelector<HTMLTextAreaElement>(SELECTOR_TEXTAREA);
private async getTextArea(): Promise<HTMLTextAreaElement> {
const textArea = document.querySelector<HTMLTextAreaElement>(
this.textAreaSelector
);

if (!textArea) throw new Error('Could not find text area');

this.textArea = textArea;
return textArea;
}

private async addTemplates() {
private async addTemplates(): Promise<HTMLUListElement> {
const parent = this.textArea.parentNode;
if (!parent) throw new Error('Could not find parent node');

Expand All @@ -46,7 +45,7 @@ export class ChatGPTDom {

for (const template of templates) {
const option = document.createElement('div');
option.classList.add(...CLASS_OPTIONS);
option.classList.add(...this.templateClasses);
option.textContent = template.name;
option.addEventListener('click', () => {
this.selectTemplatesMode = false;
Expand All @@ -58,7 +57,7 @@ export class ChatGPTDom {
dropdown.style.display = 'none';

parent.insertBefore(dropdown, this.textArea.nextSibling);
this.templatesList = dropdown;
return dropdown;
}

private async showTemplates() {
Expand Down Expand Up @@ -127,11 +126,11 @@ export class ChatGPTDom {

// Remove the "selected" class from all templates
for (let i = 0; i < items.length; i++) {
items[i].classList.remove(CLASS_SELECTED);
items[i].classList.remove(this.selectedClassName);
}

// Add the "selected" class to the template at the given index
items[index].classList.add(CLASS_SELECTED);
items[index].classList.add(this.selectedClassName);

// Scroll down if last visible item is selected and down arrow key is pressed
if (index >= lastVisibleIndex && index < items.length - 1) {
Expand All @@ -158,27 +157,4 @@ export class ChatGPTDom {
}px`;
this.hideTemplates();
}

private setText(text: string) {
this.textArea.focus();
this.textArea.value = text;
this.textArea.style.height = this.textArea.scrollHeight + 'px';
}

private simulateTyping(text: string) {
this.textArea.value = '';
let i = 0;
const intervalId = setInterval(() => {
if (i >= text.length) {
clearInterval(intervalId);
return;
}
const char = text[i];
this.textArea.value += text[i];
const event = new KeyboardEvent('keypress', { key: char });
this.textArea.dispatchEvent(event);
this.textArea.style.height = this.textArea.scrollHeight + 'px';
i++;
}, 20); // type one character every 20ms
}
}
41 changes: 41 additions & 0 deletions packages/chrome-extension/src/llms/chatgpt/chatgpt.dom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { BaseDom } from '../../base.dom';

export class ChatGPTDom extends BaseDom {
protected name = 'ChatGPT';
protected textAreaSelector = 'div.relative > textarea';
protected templateClasses = [
'p-2',
'cursor-pointer',
'hover:bg-gray-200',
'dark:hover:bg-gray-800',
];
protected selectedClassName = 'bg-gray-200';

selectedIndex = -1;
textArea!: HTMLTextAreaElement;
templatesList!: HTMLUListElement;
selectTemplatesMode = false;

protected setText(text: string) {
this.textArea.focus();
this.textArea.value = text;
this.textArea.style.height = this.textArea.scrollHeight + 'px';
}

private simulateTyping(text: string) {
this.textArea.value = '';
let i = 0;
const intervalId = setInterval(() => {
if (i >= text.length) {
clearInterval(intervalId);
return;
}
const char = text[i];
this.textArea.value += text[i];
const event = new KeyboardEvent('keypress', { key: char });
this.textArea.dispatchEvent(event);
this.textArea.style.height = this.textArea.scrollHeight + 'px';
i++;
}, 20); // type one character every 20ms
}
}
File renamed without changes.
4 changes: 2 additions & 2 deletions packages/chrome-extension/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ module.exports = composePlugins(withNx(), withReact(), (config) => {
chatgptContentScript: path.join(
config.context,
'src',
'components',
'llms',
'chatgpt',
'index.ts'
),
Expand Down Expand Up @@ -161,7 +161,7 @@ module.exports = composePlugins(withNx(), withReact(), (config) => {
new CopyWebpackPlugin({
patterns: [
{
from: 'src/components/chatgpt/chatgpt.content.styles.css',
from: 'src/llms/chatgpt/chatgpt.content.styles.css',
to: path.join(config.output.path),
force: true,
},
Expand Down

0 comments on commit 56e20e3

Please sign in to comment.