Skip to content

Commit

Permalink
feat: add button which adds followed profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
maui-r committed Nov 23, 2022
1 parent 35f2b94 commit ae5093e
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/components/NodeDetails/LinearBuffer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const LinearBuffer = ({ progressValue, bufferOffset, maxValue }: { progre

return (
<Box sx={{ width: '100%' }}>
<Tooltip title={`visible: ${netProgress}, without profile: ${bufferOffset ?? 0}`}>
<Tooltip title={`added: ${netProgress}, without profile: ${bufferOffset ?? 0}`}>
<LinearProgress variant='buffer' value={normalize(netProgress)} valueBuffer={normalize(progressValue ?? 0)} />
</Tooltip>
</Box>
Expand Down
99 changes: 89 additions & 10 deletions src/components/NodeDetails/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { getOptimisticTransactionStatus } from '../../lens/optimisticTransaction
import { broadcastTypedData } from '../../lens/broadcast'
import { createUnfollowTypedData } from '../../lens/unfollow'
import { ProfilePicture } from '../Shared/ProfilePicture'
import { getAllFollowing, getFollowers } from '../../subgraph'
import { getAllFollowing, getFollowers, getFollowing } from '../../subgraph'

const ProfileStatCard = styled(Card)(({ theme }) => ({}))
const ProfileStatWrapper = styled('div')(({ theme }) => ({
Expand Down Expand Up @@ -371,8 +371,19 @@ const UnfollowButton = ({ profile, refetchProfile }: { profile: Pick<Profile, 'i
)
}

const QueryFollowersButton = ({ profileId }: { profileId: string }) => {
const AddButton = ({ onClick, text }: { onClick: React.MouseEventHandler<HTMLButtonElement> | undefined, text: string | null }) => {
const isQuerying = useAppStore((state) => state.isQuerying)

if (!text) return null
if (isQuerying) return <Button variant='outlined' size='small' disabled>{text}</Button>
return (
<Tooltip title='Add to graph'>
<Button variant='outlined' size='small' onClick={onClick}>{text}</Button>
</Tooltip>
)
}

const QueryFollowersButton = ({ profileId }: { profileId: string }) => {
const setIsQuerying = useAppStore((state) => state.setIsQuerying)
const setQueryProgress = useAppStore((state) => state.setQueryProgress)
const addNodes = useNodeStore((state) => state.addNodes)
Expand Down Expand Up @@ -452,13 +463,80 @@ const QueryFollowersButton = ({ profileId }: { profileId: string }) => {
!node.queriedFollowers.allQueried ? 'Add more' :
null

if (!buttonText) return null
if (isQuerying) return <Button variant='outlined' size='small' disabled>{buttonText}</Button>
return (
<Tooltip title='Add to graph'>
<Button variant='outlined' size='small' onClick={handleAddFollowers}>{buttonText}</Button>
</Tooltip>
)
return <AddButton onClick={handleAddFollowers} text={buttonText} />
}

const QueryFollowingButton = ({ profileId }: { profileId: string }) => {
const setIsQuerying = useAppStore((state) => state.setIsQuerying)
const setQueryProgress = useAppStore((state) => state.setQueryProgress)
const addNodes = useNodeStore((state) => state.addNodes)
const nodes = useNodeStore((state) => state.nodes)
const node = nodes[profileId]

const handleAddFollowing = async () => {
if (!node) return
setIsQuerying(true)
setQueryProgress(0)
try {
if (node.queriedFollowing?.allQueried) return
console.debug('- add following of', profileId)

// Number of additional following to query
const followingToQuery = 25

// Get the following profile ids
let queried = node.queriedFollowing?.queried ?? 0
const followingProfiles = await getFollowing({
ethereumAddress: node.ownedBy,
first: followingToQuery,
skip: queried,
})
const followingReceived = followingProfiles.length

let followingQueried = 0
const newNodes = []
for (const profileId of followingProfiles) {
queried++

// Check if profile already present
if (nodes.hasOwnProperty(profileId)) {
console.debug('--> already present:', profileId)
setQueryProgress(++followingQueried / followingReceived)
continue
}

const profileMin = await getProfileMin({ id: profileId })
console.debug('-> got profile', profileMin.handle)

// Get following
const following = await getAllFollowing(profileMin.ownedBy)

if (Object.keys(useNodeStore.getState().nodes).length < 10) {
// Add node immediately to give the user something to explore
addNodes([{ ...profileMin, following }, { ...node, queriedFollowing: { queried } }])
} else {
newNodes.push({ ...profileMin, following })
}
console.debug('--> added')
setQueryProgress(++followingQueried / followingReceived)
}

// Update "origin" node
const allQueried = followingReceived < followingToQuery
newNodes.push({ ...node, queriedFollowing: { queried, allQueried } })

addNodes(newNodes)
} finally {
setIsQuerying(false)
setQueryProgress(null)
}
}

const buttonText = !node.queriedFollowing ? 'Add' :
!node.queriedFollowing.allQueried ? 'Add more' :
null

return <AddButton onClick={handleAddFollowing} text={buttonText} />
}

const ProfileDetails = ({ profileId }: { profileId: string }) => {
Expand Down Expand Up @@ -514,12 +592,13 @@ const ProfileDetails = ({ profileId }: { profileId: string }) => {
</ProfileStatWrapper>
</ProfileStatCard>
<ProfileStatCard variant='outlined'>
<LinearBuffer progressValue={node.queriedFollowing?.queried} bufferOffset={0} maxValue={profile.stats.totalFollowing} />
<ProfileStatWrapper>
<Box>
<ProfileStatValue>{profile.stats.totalFollowing}</ProfileStatValue>
<ProfileStatName>Following</ProfileStatName>
</Box>
{/* <AddFollowingButton profileId={profileId} /> */}
{profile.stats.totalFollowing ? <QueryFollowingButton profileId={profileId} /> : null}
</ProfileStatWrapper>
</ProfileStatCard>
<ProfileStatCard variant='outlined'>
Expand Down
30 changes: 30 additions & 0 deletions src/subgraph/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,34 @@ export const getFollowers = async ({ profileId, first, skip = 0 }: { profileId:
}

return result.data.profile.followers.map((f: { account: { id: string } }) => (f.account.id))
}

const FollowedByAddressSortedQuery = `
query FollowedByAddress($ethereumAddress: Bytes!, $first: Int!, $skip: Int!) {
account(id: $ethereumAddress) {
following(first: $first, skip: $skip, orderBy: timestamp, orderDirection: asc) {
profile {
id
}
}
}
}
`

export const getFollowing = async ({ ethereumAddress, first, skip = 0 }: { ethereumAddress: string, first: number, skip: number }): Promise<string[]> => {
await sleep(REQUEST_DELAY)
const result = await client
.query(FollowedByAddressSortedQuery, { ethereumAddress, first, skip })
.toPromise()

if (!result.data) {
throw new Error('No result data')
}

if (!result.data.account?.following) {
// Address is not following anyone
return []
}

return result.data.account.following.map((f: { profile: { id: string } }) => (f.profile.id))
}
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export enum ColorMode {

export type QueryState = {
queried: number,
withoutProfile: number,
withoutProfile?: number,
allQueried?: boolean,
}

Expand All @@ -21,6 +21,7 @@ export type Profile = {
ownedBy: string,
following: Array<Node['id']>,
queriedFollowers?: QueryState,
queriedFollowing?: QueryState,
}

export type Node = Profile
Expand Down

0 comments on commit ae5093e

Please sign in to comment.