Skip to content

Commit

Permalink
feat: add badge and make tooltip toggleable
Browse files Browse the repository at this point in the history
  • Loading branch information
ivangabriele committed Nov 12, 2023
1 parent f36323c commit 11219b8
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 64 deletions.
17 changes: 17 additions & 0 deletions assets/icon-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ async function handleTabUpdated(
}

await sendState(tabId, State.MATCHED)

startWebSocketClient(tabId)
}

Expand Down
10 changes: 10 additions & 0 deletions common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@ import { State } from './types'

export const RECONNECTION_DELAY_IN_MS = 5000

export const STATE_CSS_CLASS: Record<State, string> = {
[State.CONNECTING]: 'is-loading',
[State.CONNECTED]: 'is-connected',
[State.DISCONNECTED]: 'is-disconnected',
[State.DISCONNECTING]: 'is-loading',
[State.MATCHED]: 'is-loading',
[State.RECONNECTING]: 'is-loading',
[State.WILL_RECONNECT]: 'is-loading',
}

export const STATE_LABEL: Record<State, string> = {
[State.CONNECTING]: 'Connecting...',
[State.CONNECTED]: 'Connected.',
Expand Down
85 changes: 75 additions & 10 deletions content/index.css
Original file line number Diff line number Diff line change
@@ -1,21 +1,86 @@
#openai-forge {
/***********************************************************
Box
*/

#openai-forge * {
box-sizing: border-box;
}

/***********************************************************
Badge
*/

#openai-forge .Badge {
align-items: center;
background-color: rgba(255, 255, 255, 0.1);
bottom: 12px;
border: solid 1px rgba(255, 255, 255, 0.1);
border-radius: 50%;
display: flex;
height: 26px;
justify-content: center;
padding: 0 0 2px 1px;
position: fixed;
right: 12px;
width: 26px;
}
@media (min-width: 1024px) {
#openai-forge .Badge {
right: 50px;
}
}
#openai-forge .Badge.has-error {
background-color: #fc3623;
}
#openai-forge .Badge.is-connected {
background-color: #e52b50;
}
#openai-forge .Badge.is-disconnected {
background-color: #000000;
}
#openai-forge .Badge.is-loading {
background-color: #fc3623;
}

#openai-forge .Badge img {
height: 16px;
width: 16px;
}
@keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
#openai-forge .Badge.is-loading img {
animation: rotation 2s infinite linear;
}

/***********************************************************
Tooltip
*/

#openai-forge .Tooltip {
bottom: 50px;
box-sizing: border-box;
display: flex;
flex-direction: column;
font-family: sans-serif;
line-height: 1;
pointer-events: none;
position: fixed;
right: 0;
top: 0;
right: -240px;
transition: transform 0.25s ease-in-out;
user-select: none;
width: 224px;
width: 240px;
}

#openai-forge * {
box-sizing: border-box;
#openai-forge .Tooltip.is-open {
transform: translate(-240px, 0);
}

#openai-forge .header {
#openai-forge .Tooltip-header {
align-items: center;
background-color: #e52b50;
color: white;
Expand All @@ -25,7 +90,7 @@
padding: 0 6px 2px;
}

#openai-forge .body {
#openai-forge .Tooltip-body {
align-items: center;
background-color: #222222;
color: white;
Expand All @@ -34,6 +99,6 @@
height: 26px;
padding: 0 6px 0;
}
#openai-forge .body.has-error {
#openai-forge .Tooltip-body.has-error {
background-color: #fc3623;
}
106 changes: 85 additions & 21 deletions content/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,42 @@
import { STATE_LABEL } from '../common/constants'
import { RequestType, type Request, Action } from '../common/types'
import { STATE_CSS_CLASS, STATE_LABEL } from '../common/constants'
import { RequestType, type Request, Action, State } from '../common/types'

function updatedBadge(message: string, isError: boolean = false) {
bodyElement.innerText = message
function clearBadgeCssClasses() {
badgeElement.classList.forEach(className => {
if (['Badge', 'is-open'].includes(className)) {
return
}

badgeElement.classList.remove(className)
})
}

function setBadgeError(errorMessage: string) {
if (!tooltipBodyElement.classList.contains('has-error')) {
tooltipBodyElement.classList.add('has-error')
}

tooltipBodyElement.innerText = errorMessage
}

function toggleTooltip() {
const isTooltipOpen = tootipElement.classList.contains('is-open')

if (isTooltipOpen) {
tootipElement.classList.remove('is-open')
} else {
tootipElement.classList.add('is-open')
}
}

function updateBadgeState(nextState: State) {
clearBadgeCssClasses()
badgeElement.classList.add(STATE_CSS_CLASS[nextState])

if (isError && !bodyElement.classList.contains('with-error')) {
bodyElement.classList.add('with-error')
} else if (bodyElement.classList.contains('with-error')) {
bodyElement.classList.remove('with-error')
if (tooltipBodyElement.classList.contains('has-error')) {
tooltipBodyElement.classList.remove('has-error')
}
tooltipBodyElement.innerText = STATE_LABEL[nextState]
}

chrome.runtime.onMessage.addListener((request: Request) => {
Expand Down Expand Up @@ -42,27 +70,63 @@ chrome.runtime.onMessage.addListener((request: Request) => {
}

if (request.type === RequestType.ERROR) {
updatedBadge(request.value, true)
setBadgeError(request.value)
}

if (request.type === RequestType.STATE) {
updatedBadge(STATE_LABEL[request.value])
updateBadgeState(request.value)
}
})

const rootElement = document.createElement('div')
rootElement.id = 'openai-forge'
const IS_DARK_MODE = document.querySelector('html')?.classList.contains('dark')

// ---------------------------------------------------------
// Box

const boxElement = document.createElement('div')
boxElement.id = 'openai-forge'

// ---------------------------------------------------------
// Badge

const badgeElement = document.createElement('button')
badgeElement.classList.add('Badge')

const buttonElementIconUrl = IS_DARK_MODE
? chrome.runtime.getURL('assets/icon-dark.svg')
: chrome.runtime.getURL('assets/icon.svg')
const badgeImageElement = document.createElement('img')
badgeImageElement.src = buttonElementIconUrl
badgeElement.appendChild(badgeImageElement)

badgeElement.addEventListener('click', toggleTooltip)

boxElement.appendChild(badgeElement)

// ---------------------------------------------------------
// Tooltip

const tootipElement = document.createElement('div')
tootipElement.classList.add('Tooltip')

const tooltipHeaderElement = document.createElement('div')
tooltipHeaderElement.classList.add('Tooltip-header')
tooltipHeaderElement.innerText = 'OpenAI Forge'
tootipElement.appendChild(tooltipHeaderElement)

const tooltipBodyElement = document.createElement('div')
tooltipBodyElement.classList.add('Tooltip-body')
tooltipBodyElement.innerText = 'Loaddng...'
tootipElement.appendChild(tooltipBodyElement)

boxElement.appendChild(tootipElement)

const headerElement = document.createElement('div')
headerElement.classList.add('header')
headerElement.innerText = 'OpenAI Forge'
// ---------------------------------------------------------
// DOM initialization

const bodyElement = document.createElement('div')
bodyElement.classList.add('body')
bodyElement.innerText = 'Loaddng...'
document.body.appendChild(boxElement)

rootElement.appendChild(headerElement)
rootElement.appendChild(bodyElement)
document.body.appendChild(rootElement)
// ---------------------------------------------------------
// Sanity check

console.debug('OpenAI Forge', 'Content script loaded.')
28 changes: 13 additions & 15 deletions manifest.chrome.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,25 @@
},
"content_scripts": [
{
"matches": [
"https://chat.openai.com/*"
],
"css": [
"content.css"
],
"js": [
"content.js"
]
"matches": ["https://chat.openai.com/*"],
"css": ["content.css"],
"js": ["content.js"]
}
],
"content_security_policy": {
"extension_pages": "default-src 'self'; connect-src 'self' http://localhost:4242 ws://localhost:4242;"
"extension_pages": "default-src 'self'; connect-src 'self' http://localhost:4242 ws://localhost:4242; img-src chrome-extension:;"
},
"host_permissions": [
"https://chat.openai.com/*"
],
"host_permissions": ["https://chat.openai.com/*"],
"icons": {
"16": "assets/icons/x16.png",
"32": "assets/icons/x16.png",
"48": "assets/icons/x48.png",
"128": "assets/icons/x128.png"
}
}
},
"web_accessible_resources": [
{
"resources": ["assets/icon.svg", "assets/icon-dark.svg"],
"matches": ["https://chat.openai.com/*"]
}
]
}
32 changes: 14 additions & 18 deletions manifest.firefox.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
"default_popup": "popup.html"
},
"background": {
"scripts": [
"background.js"
],
"scripts": ["background.js"],
"type": "module"
},
"browser_specific_settings": {
Expand All @@ -19,32 +17,30 @@
}
},
"content_security_policy": {
"extension_pages": "default-src 'self'; connect-src 'self' http://localhost:4242 ws://localhost:4242;"
"extension_pages": "default-src 'self'; connect-src 'self' http://localhost:4242 ws://localhost:4242; img-src moz-extension:;"
},
"content_scripts": [
{
"matches": [
"https://chat.openai.com/*"
],
"css": [
"content.css"
],
"js": [
"content.js"
]
"matches": ["https://chat.openai.com/*"],
"css": ["content.css"],
"js": ["content.js"]
}
],
"developer": {
"name": "Ivan Gabriele",
"url": "https://www.ivangabriele.com"
},
"host_permissions": [
"https://chat.openai.com/*"
],
"host_permissions": ["https://chat.openai.com/*"],
"icons": {
"16": "assets/icons/x16.png",
"32": "assets/icons/x16.png",
"48": "assets/icons/x48.png",
"128": "assets/icons/x128.png"
}
}
},
"web_accessible_resources": [
{
"resources": ["assets/icon.svg", "assets/icon-dark.svg"],
"matches": ["https://chat.openai.com/*"]
}
]
}
2 changes: 2 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ export default defineConfig([
targets: [
// Chrome
{ dest: './dist/chrome/assets', src: './assets/icons' },
{ dest: './dist/chrome/assets', src: './assets/icon.svg' },
{ dest: './dist/chrome/assets', src: './assets/icon-dark.svg' },
{ dest: './dist/chrome', rename: 'content.css', src: './content/index.css' },
{ dest: './dist/chrome', rename: 'popup.css', src: './popup/index.css' },
{ dest: './dist/chrome', rename: 'popup.html', src: './popup/index.html' },
Expand Down

0 comments on commit 11219b8

Please sign in to comment.