Skip to content

Commit 2334895

Browse files
committed
Leverage the typesystem.
1 parent f3734c6 commit 2334895

File tree

3 files changed

+121
-24
lines changed

3 files changed

+121
-24
lines changed

browser-extension/src/entrypoints/background.ts

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import type { CommentDraft, CommentEvent, CommentSpot } from '../lib/enhancer'
22
import { JsonMap } from '../lib/jsonmap'
3+
import type { GetOpenSpotsResponse, ToBackgroundMessage } from '../lib/messages'
4+
import {
5+
isContentToBackgroundMessage,
6+
isGetOpenSpotsMessage,
7+
isSwitchToTabMessage,
8+
} from '../lib/messages'
39

410
export interface Tab {
511
tabId: number
@@ -46,30 +52,38 @@ export function handleCommentEvent(message: CommentEvent, sender: any): void {
4652
}
4753
}
4854

49-
export function handlePopupMessage(message: any, _sender: any, sendResponse: (response: any) => void): void {
50-
if (message.type === 'GET_OPEN_SPOTS') {
55+
export function handlePopupMessage(
56+
message: any,
57+
_sender: any,
58+
sendResponse: (response: any) => void,
59+
): void {
60+
if (isGetOpenSpotsMessage(message)) {
5161
const spots: CommentState[] = []
5262
for (const [, commentState] of openSpots) {
5363
spots.push(commentState)
5464
}
55-
sendResponse({ spots })
56-
} else if (message.type === 'SWITCH_TO_TAB') {
57-
browser.windows.update(message.windowId, { focused: true }).then(() => {
58-
return browser.tabs.update(message.tabId, { active: true })
59-
}).catch(error => {
60-
console.error('Error switching to tab:', error)
61-
})
65+
const response: GetOpenSpotsResponse = { spots }
66+
sendResponse(response)
67+
} else if (isSwitchToTabMessage(message)) {
68+
browser.windows
69+
.update(message.windowId, { focused: true })
70+
.then(() => {
71+
return browser.tabs.update(message.tabId, { active: true })
72+
})
73+
.catch((error) => {
74+
console.error('Error switching to tab:', error)
75+
})
6276
}
6377
}
6478

6579
export default defineBackground(() => {
66-
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
67-
if (message.type === 'GET_OPEN_SPOTS' || message.type === 'SWITCH_TO_TAB') {
68-
handlePopupMessage(message, sender, sendResponse)
69-
return true
70-
} else {
80+
browser.runtime.onMessage.addListener((message: ToBackgroundMessage, sender, sendResponse) => {
81+
if (isContentToBackgroundMessage(message)) {
7182
handleCommentEvent(message, sender)
7283
return false
84+
} else {
85+
handlePopupMessage(message, sender, sendResponse)
86+
return true
7387
}
7488
})
7589
})

browser-extension/src/entrypoints/popup/main.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import './style.css'
2-
import type { CommentState } from '../background'
3-
import { EnhancerRegistry } from '../../lib/registries'
42
import { logger } from '../../lib/logger'
3+
import type {
4+
GetOpenSpotsMessage,
5+
GetOpenSpotsResponse,
6+
SwitchToTabMessage,
7+
} from '../../lib/messages'
8+
import { EnhancerRegistry } from '../../lib/registries'
9+
import type { CommentState } from '../background'
510

611
// Test basic DOM access
712
try {
8-
const app = document.getElementById('app')!!
13+
const app = document.getElementById('app')!
914
logger.debug('Found app element:', app)
1015
app.innerHTML = '<div>Script is running...</div>'
1116
} catch (error) {
@@ -17,7 +22,8 @@ const enhancers = new EnhancerRegistry()
1722
async function getOpenSpots(): Promise<CommentState[]> {
1823
logger.debug('Sending message to background script...')
1924
try {
20-
const response = await browser.runtime.sendMessage({ type: 'GET_OPEN_SPOTS' })
25+
const message: GetOpenSpotsMessage = { type: 'GET_OPEN_SPOTS' }
26+
const response = (await browser.runtime.sendMessage(message)) as GetOpenSpotsResponse
2127
logger.debug('Received response:', response)
2228
return response.spots || []
2329
} catch (error) {
@@ -29,11 +35,12 @@ async function getOpenSpots(): Promise<CommentState[]> {
2935
function switchToTab(tabId: number, windowId: number): void {
3036
// Send message to background script to handle tab switching
3137
// This avoids the popup context being destroyed before completion
32-
browser.runtime.sendMessage({
33-
type: 'SWITCH_TO_TAB',
38+
const message: SwitchToTabMessage = {
3439
tabId,
35-
windowId
36-
})
40+
type: 'SWITCH_TO_TAB',
41+
windowId,
42+
}
43+
browser.runtime.sendMessage(message)
3744
window.close()
3845
}
3946

@@ -76,14 +83,14 @@ async function renderOpenSpots(): Promise<void> {
7683
const list = document.createElement('div')
7784
list.className = 'spots-list'
7885

79-
spots.forEach(spot => {
86+
spots.forEach((spot) => {
8087
list.appendChild(createSpotElement(spot))
8188
})
8289

8390
app.appendChild(list)
8491
}
8592

86-
renderOpenSpots().catch(error => {
93+
renderOpenSpots().catch((error) => {
8794
logger.error('Error in renderOpenSpots:', error)
8895
const app = document.getElementById('app')!
8996
app.innerHTML = `<div class="no-spots">Error loading spots: ${error.message}</div>`
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import type { CommentDraft, CommentEvent, CommentSpot } from './enhancer'
2+
3+
// Content -> Background messages (already well-typed as CommentEvent)
4+
export type ContentToBackgroundMessage = CommentEvent
5+
6+
// Popup -> Background messages
7+
export interface GetOpenSpotsMessage {
8+
type: 'GET_OPEN_SPOTS'
9+
}
10+
11+
export interface SwitchToTabMessage {
12+
type: 'SWITCH_TO_TAB'
13+
tabId: number
14+
windowId: number
15+
}
16+
17+
export type PopupToBackgroundMessage = GetOpenSpotsMessage | SwitchToTabMessage
18+
19+
// All messages sent to background
20+
export type ToBackgroundMessage = ContentToBackgroundMessage | PopupToBackgroundMessage
21+
22+
// Background -> Popup responses
23+
export interface GetOpenSpotsResponse {
24+
spots: Array<{
25+
tab: {
26+
tabId: number
27+
windowId: number
28+
}
29+
spot: CommentSpot
30+
drafts: Array<[number, CommentDraft]>
31+
}>
32+
}
33+
34+
// Type guard functions
35+
export function isContentToBackgroundMessage(message: any): message is ContentToBackgroundMessage {
36+
return (
37+
message &&
38+
typeof message.type === 'string' &&
39+
(message.type === 'ENHANCED' || message.type === 'DESTROYED') &&
40+
message.spot
41+
)
42+
}
43+
44+
export function isPopupToBackgroundMessage(message: any): message is PopupToBackgroundMessage {
45+
return (
46+
message &&
47+
typeof message.type === 'string' &&
48+
(message.type === 'GET_OPEN_SPOTS' || message.type === 'SWITCH_TO_TAB')
49+
)
50+
}
51+
52+
export function isGetOpenSpotsMessage(message: any): message is GetOpenSpotsMessage {
53+
return message && message.type === 'GET_OPEN_SPOTS'
54+
}
55+
56+
export function isSwitchToTabMessage(message: any): message is SwitchToTabMessage {
57+
return (
58+
message &&
59+
message.type === 'SWITCH_TO_TAB' &&
60+
typeof message.tabId === 'number' &&
61+
typeof message.windowId === 'number'
62+
)
63+
}
64+
65+
// Message handler types
66+
export type BackgroundMessageHandler = (
67+
message: ToBackgroundMessage,
68+
sender: any,
69+
sendResponse: (response?: any) => void,
70+
) => boolean | undefined
71+
72+
export type PopupMessageSender = {
73+
sendMessage<T extends PopupToBackgroundMessage>(
74+
message: T,
75+
): Promise<T extends GetOpenSpotsMessage ? GetOpenSpotsResponse : void>
76+
}

0 commit comments

Comments
 (0)