-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
chore: move attachment link back to tree item, make it flash yellow #34353
base: main
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
packages/web/src/uiUtils.ts
Outdated
@@ -224,3 +224,16 @@ export function scrollIntoViewIfNeeded(element: Element | undefined) { | |||
|
|||
const kControlCodesRe = '\\u0000-\\u0020\\u007f-\\u009f'; | |||
export const kWebLinkRe = new RegExp('(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\\/\\/|www\\.)[^\\s' + kControlCodesRe + '"]{2,}[^\\s' + kControlCodesRe + '"\')}\\],:;.!?]', 'ug'); | |||
|
|||
// flash is retriggered whenever the value changes | |||
export function useFlash(flash: any | undefined) { |
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.
What's the semantic? Whenever flash
is truthy it is going to "flash" and unflash in a second? Should this be flash: boolean
instead?
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.
whenever flash
changes its value, useFlash
returns true for two seconds. if it were flash: boolean
then you couldn't retrigger it. it depends on something where it can compare references
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.
This API signature should be const useFlash = (): [boolean, () => void]
You return a function that, when called, triggers the flash by updating state. You have a useState
with an incrementing counter to trigger rerenders (i.e. the useEffect
dependencies array contains the state number).
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.
In particular it looks like you want your setFlash
to take an ID object (we can just use the attachment itself), which is then cleared when the timer finishes. You then compare against that ID object to determine if you want to flash that particular attachment when it changes.
I believe you also trigger your scrollTo
when you have a matching flash object.
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.
How's that different from the current implementation, apart from the placement of the useEffect?
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.
export function useFlash(flash: any | undefined) { | |
export function useFlash(idObject?: any) { |
This comment has been minimized.
This comment has been minimized.
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.
Visually it looks good. Left some comments on the React bits.
packages/web/src/uiUtils.ts
Outdated
@@ -224,3 +224,16 @@ export function scrollIntoViewIfNeeded(element: Element | undefined) { | |||
|
|||
const kControlCodesRe = '\\u0000-\\u0020\\u007f-\\u009f'; | |||
export const kWebLinkRe = new RegExp('(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\\/\\/|www\\.)[^\\s' + kControlCodesRe + '"]{2,}[^\\s' + kControlCodesRe + '"\')}\\],:;.!?]', 'ug'); | |||
|
|||
// flash is retriggered whenever the value changes | |||
export function useFlash(flash: any | undefined) { |
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.
This API signature should be const useFlash = (): [boolean, () => void]
You return a function that, when called, triggers the flash by updating state. You have a useState
with an incrementing counter to trigger rerenders (i.e. the useEffect
dependencies array contains the state number).
packages/web/src/uiUtils.ts
Outdated
@@ -224,3 +224,16 @@ export function scrollIntoViewIfNeeded(element: Element | undefined) { | |||
|
|||
const kControlCodesRe = '\\u0000-\\u0020\\u007f-\\u009f'; | |||
export const kWebLinkRe = new RegExp('(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\\/\\/|www\\.)[^\\s' + kControlCodesRe + '"]{2,}[^\\s' + kControlCodesRe + '"\')}\\],:;.!?]', 'ug'); | |||
|
|||
// flash is retriggered whenever the value changes | |||
export function useFlash(flash: any | undefined) { |
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.
In particular it looks like you want your setFlash
to take an ID object (we can just use the attachment itself), which is then cleared when the timer finishes. You then compare against that ID object to determine if you want to flash that particular attachment when it changes.
I believe you also trigger your scrollTo
when you have a matching flash object.
@@ -148,7 +148,7 @@ export const Workbench: React.FunctionComponent<{ | |||
|
|||
const revealAttachment = React.useCallback((attachment: AfterActionTraceEventAttachment) => { | |||
selectPropertiesTab('attachments'); | |||
setRevealedAttachment(attachment); | |||
setRevealedAttachment({ ...attachment }); // copy to force re-render |
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.
I'm not seeing why this clone is necessary, and in general causing rerenders in this manner is bad practice as it's difficult to track down why stuff is behaving as it is.
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.
It'll be passed to a useEffect
down the line, so we need to do something to break Object.is
equality to allow flashing the same attachment twice in a row.
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.
Revisiting this, you're right. Cloning an object is hard to debug because both objects will look the same. I've refactored it to use an incrementing counter instead.
I refactored things a little. It's now also handling the case where the animation is retriggered while it's still ongoing https://github.com/user-attachments/assets/71432bf6-9b9b-436a-87f9-41c1671c9f46 |
This comment has been minimized.
This comment has been minimized.
@@ -224,3 +225,22 @@ export function scrollIntoViewIfNeeded(element: Element | undefined) { | |||
|
|||
const kControlCodesRe = '\\u0000-\\u0020\\u007f-\\u009f'; | |||
export const kWebLinkRe = new RegExp('(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\\/\\/|www\\.)[^\\s' + kControlCodesRe + '"]{2,}[^\\s' + kControlCodesRe + '"\')}\\],:;.!?]', 'ug'); | |||
|
|||
export function useFlash(): [boolean, EffectCallback] { |
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.
IIUC, this is only needed to re-trigger the animation mid-flight? Otherwise, we'd just set the css class when needed, and the animation will play by itself?
If so, please add a comment explaining this. I am not 100% sure it's worth the complexity, but I leave that up to you.
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.
The important bit is that the css class is removed after a second, so the animation can be played multiple times.
I've added a comment to explain that.
|
||
type Attachment = AfterActionTraceEventAttachment & { traceUrl: string }; | ||
|
||
type ExpandableAttachmentProps = { | ||
attachment: Attachment; | ||
reveal: boolean; | ||
highlight: boolean; | ||
reveal?: any; |
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.
It seems like you can revert this back to be a boolean? I don't see why it should be different now with the yellow flash compared to scrolling into view.
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.
Just like with scrolling into view, we need this to be an ID object so we can retrigger the animation. I think there was a bug with scroll into view before, where it didn't retrigger when clicking the same button twice. But it wasn't as noticeable because you'd have to scroll around between clicking the button.
@@ -148,7 +148,12 @@ export const Workbench: React.FunctionComponent<{ | |||
|
|||
const revealAttachment = React.useCallback((attachment: AfterActionTraceEventAttachment) => { | |||
selectPropertiesTab('attachments'); | |||
setRevealedAttachment(attachment); | |||
setRevealedAttachment(currentValue => { |
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.
It looks to me this can be reverted.
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.
Nope, this is required that to re-trigger the animation. We're discussing the specific form in #34353 (comment). We don't need it in the HTML reporter because we have the URLSearchParams
context, but that's not a thing in the trace viewer.
This comment has been minimized.
This comment has been minimized.
Test results for "tests 1"10 flaky37593 passed, 648 skipped Merge workflow run. |
Screen.Recording.2025-01-16.at.13.33.42.mov
Screen.Recording.2025-01-16.at.15.03.10.mov