-
Notifications
You must be signed in to change notification settings - Fork 393
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
Support video avatars #3700
Support video avatars #3700
Changes from 5 commits
242cd84
6f464e6
ccb4679
a4feb8e
b3d30f5
c74eabf
2cca702
58d05ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { DomainName, URI } from "../../types" | ||
|
||
type OldState = { | ||
assets: unknown[] | ||
account: { | ||
accountsData: { | ||
evm: { | ||
[chainID: string]: { | ||
[address: string]: | ||
| "loading" | ||
| { | ||
ens: { | ||
name?: DomainName | ||
avatarURL?: URI | ||
avatarType?: string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. old state shouldn't have |
||
} | ||
[other: string]: unknown | ||
} | ||
} | ||
} | ||
} | ||
[sliceKey: string]: unknown | ||
} | ||
[otherSlice: string]: unknown | ||
} | ||
|
||
type NewState = { | ||
assets: unknown[] | ||
account: { | ||
accountsData: { | ||
evm: { | ||
[chainID: string]: { | ||
[address: string]: | ||
| "loading" | ||
| { | ||
ens: { | ||
name?: DomainName | ||
avatarURL?: URI | ||
avatarType?: string | ||
} | ||
[other: string]: unknown | ||
} | ||
} | ||
} | ||
} | ||
[sliceKey: string]: unknown | ||
} | ||
[otherSlice: string]: unknown | ||
} | ||
|
||
export default (prevState: Record<string, unknown>): NewState => { | ||
const typedPrevState = prevState as OldState | ||
|
||
const { | ||
account: { accountsData }, | ||
} = typedPrevState | ||
|
||
Object.keys(accountsData.evm).forEach((chainID) => | ||
Object.keys(accountsData.evm[chainID]).forEach(async (address) => { | ||
const account = accountsData.evm[chainID][address] | ||
|
||
if (account !== "loading") { | ||
const accountData = account.ens | ||
const { avatarURL } = accountData | ||
|
||
if (!avatarURL) { | ||
accountData.avatarType = undefined | ||
} else { | ||
const fileTypeResponse = await fetch(avatarURL, { method: "HEAD" }) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm I don't think this will work correctly because we are not waiting for results here at all, script will continue sync execution and will deserialize the preloaded state without waiting for these fetches. Actually, now I'm even thinking that we shouldn't even do it here at all - migrations should be working fast and be deterministic 🤔 Sorry about making it more confusing than it should be 😓 |
||
const avatarType = fileTypeResponse.headers.get("Content-Type") | ||
|
||
accountData.avatarType = avatarType ?? undefined | ||
} | ||
} | ||
}), | ||
) | ||
|
||
return { | ||
...typedPrevState, | ||
assets: [], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why we are resetting assets? |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import React, { CSSProperties } from "react" | ||
|
||
type SharedAvatarProps = { | ||
width: string | ||
background?: string | ||
borderRadius?: string | ||
avatarURL?: string | ||
avatarType?: string | ||
backupAvatar: string | ||
style?: CSSProperties | ||
} | ||
|
||
export default function SharedAvatar({ | ||
width, | ||
background = "var(--green-40)", | ||
borderRadius = "12px", | ||
avatarURL, | ||
avatarType, | ||
backupAvatar, | ||
style, | ||
}: SharedAvatarProps) { | ||
return ( | ||
<> | ||
{avatarType === "video/mp4" ? ( | ||
<div className="video" style={style}> | ||
<video src={avatarURL} autoPlay muted loop /> | ||
</div> | ||
) : ( | ||
<div className="avatar" style={style} /> | ||
)} | ||
<style jsx>{` | ||
.avatar { | ||
width: ${width}; | ||
height: ${width}; | ||
border-radius: ${borderRadius}; | ||
flex-shrink: 0; | ||
background-color: ${background}; | ||
background: url("${avatarURL ?? backupAvatar}"); | ||
background-size: cover; | ||
background-position: center; | ||
background-repeat: no-repeat; | ||
} | ||
.video { | ||
width: ${width}; | ||
height: ${width}; | ||
border-radius: ${borderRadius}; | ||
background-color: ${background}; | ||
overflow: hidden; | ||
} | ||
.video > video { | ||
width: 100%; | ||
height: 100%; | ||
object-fit: cover; | ||
} | ||
`}</style> | ||
</> | ||
) | ||
} |
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.
FYI: This is changing shape of the redux and in the extension we are persisting redux state between reloads. Usually we are adding redux migration but in this case I think we are fine because we are ok with this field being
undefined
. Anyway - I'll test the migration to make sure it is ok.EDIT:
ok so we will need a migration unfortunately
Reproduction steps:
main
result: no avatar at all, not even the light green background
expected: there is a video avatar visible