-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Popup ready signal to service worker #174
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you confirm this solves the problem with #130? On the testnet whale, you can test this by trying to do an EndAll
on the auctions page.
Approving, but think this also requires an approval from @turbocrime as they had a vision for how this was going to work from way back.
await new Promise(resolve => setTimeout(resolve, 800)); | ||
const popupId = crypto.randomUUID(); | ||
await spawnPopup(req.type, popupId); | ||
await popupReady(popupId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: we should add a code comment here that informs devs that this is necessary given it takes a bit of time for the popup to be ready to accept messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blocking due to issues described by inline comments.
i think part of these issues are due to the lack of documentation for InternalMessage
and associated types. it is related to some of the earliest messaging work on the extension, so maybe @grod220 has some input. i will take the opportunity to explain some of the intentions as i understand them in a following comment.
apps/extension/src/message/popup.ts
Outdated
export type Ready = InternalMessage< | ||
PopupType.Ready, | ||
null, | ||
{ | ||
popupId: string; | ||
} | ||
>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (blocking)
defining an InternalMessage
with a null
second parameter and including that in the PopupMessage
union means that PopupRequest
now includes a union member shaped { type: PopupType.Ready, request: null }
, which affects methods that rely on the PopupRequest
type to constrain input.
todo:
Don't use InternalMessage
with a null
request parameter, and possibly don't use InternalMessage
at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for example, this PR presently assures the compiler this call is ok, even though it's not an intended use of this message type:
const readyResponse: { popupId: string } = await popup<Ready>({ type: PopupType.Ready, request: null });
this verifies the user is logged in, and then thankfully throws before opening a popup when the popup method can't identify a route for PopupType.Ready
.
@@ -62,3 +62,4 @@ packages/*/package | |||
|
|||
apps/extension/chromium-profile | |||
|
|||
scripts/private |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: revert gitignore diff
sorry if this is excessively thorough or verbose. you mentioned a lower it makes a lot of sense to simply add a new type string to what looks like a
|
Seems to work though it takes time @grod220 |
Thank you for the extensive write-up @turbocrime. I understand now that this message should not be of the InternalMessage type. I've refactored it according to your suggestions, please re-review. |
it looks like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
approving, but please correct use or implementation of throwIfAlreadyOpen
import { useEffect, useRef } from 'react'; | ||
import { useSearchParams } from 'react-router-dom'; | ||
|
||
type IsReady = boolean | undefined; | ||
|
||
// signals that react is ready (mounted) to service worker | ||
export const usePopupReady = (isReady: IsReady = undefined) => { | ||
const sentMessagesRef = useRef(new Set()); | ||
const [searchParams] = useSearchParams(); | ||
const popupId = searchParams.get('popupId'); | ||
|
||
useEffect(() => { | ||
if (popupId && (isReady === undefined || isReady) && !sentMessagesRef.current.has(popupId)) { | ||
sentMessagesRef.current.add(popupId); | ||
|
||
void chrome.runtime.sendMessage(popupId); | ||
} | ||
}, [popupId, isReady]); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question:
is there a reason this hook accepts a function parameter?
is there a reason that the parameter uses a named type instead of the signature (isReady?: boolean)
?
issue:
this implementation seems like it could send additional messages if the parameters change. they shouldn't, but it might be better to eliminate that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import { useEffect, useRef } from 'react'; | |
import { useSearchParams } from 'react-router-dom'; | |
type IsReady = boolean | undefined; | |
// signals that react is ready (mounted) to service worker | |
export const usePopupReady = (isReady: IsReady = undefined) => { | |
const sentMessagesRef = useRef(new Set()); | |
const [searchParams] = useSearchParams(); | |
const popupId = searchParams.get('popupId'); | |
useEffect(() => { | |
if (popupId && (isReady === undefined || isReady) && !sentMessagesRef.current.has(popupId)) { | |
sentMessagesRef.current.add(popupId); | |
void chrome.runtime.sendMessage(popupId); | |
} | |
}, [popupId, isReady]); | |
}; | |
import { useEffect, useRef } from 'react'; | |
import { useSearchParams } from 'react-router-dom'; | |
// signals that react is ready (mounted) to service worker | |
export const usePopupReady = () => { | |
const sentReady = useRef<string>(); | |
const [searchParams] = useSearchParams(); | |
useEffect(() => { | |
const popupId = searchParams.get('popupId'); | |
if (!sentReady.current && popupId) { | |
sentReady.current ??= popupId; | |
void chrome.runtime.sendMessage(sentReady.current); | |
} | |
}, [searchParams]); | |
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually we can remove the function arg, the initial idea (before I placed it into the layout) was that you would be able to control the ready state from a parent component, but this is no longer needed and overcomplicates things.
A subtle, but noticeable difference is that the extension popup content loads faster (at least for me). Nice job! |
Fixes penumbra-zone/web#285