diff --git a/packages/frontend/core/src/hooks/affine/use-members.ts b/packages/frontend/core/src/hooks/affine/use-members.ts index 0f6c78b57..af435dc48 100644 --- a/packages/frontend/core/src/hooks/affine/use-members.ts +++ b/packages/frontend/core/src/hooks/affine/use-members.ts @@ -1,10 +1,31 @@ import { type GetMembersByWorkspaceIdQuery, getMembersByWorkspaceIdQuery, + Permission, } from '@affine/graphql'; +import { useMemo } from 'react'; import { useQuery } from '../use-query'; +export function calculateWeight(member: Member) { + const permissionWeight = { + [Permission.Owner]: 4, + [Permission.Admin]: 3, + [Permission.Write]: 2, + [Permission.Read]: 1, + }; + + const factors = [ + Number(member.permission === Permission.Owner), // Owner weight is the highest + Number(!member.accepted), // Unaccepted members are before accepted members + permissionWeight[member.permission] || 0, + ]; + + return factors.reduce((ret, factor, index, arr) => { + return ret + factor * Math.pow(10, arr.length - 1 - index); + }, 0); +} + export type Member = Omit< GetMembersByWorkspaceIdQuery['workspace']['members'][number], '__typename' @@ -22,5 +43,20 @@ export function useMembers( take, }, }); - return data.workspace.members; + + const members = data.workspace.members; + + return useMemo(() => { + // sort members by weight + return members.sort((a, b) => { + const weightDifference = calculateWeight(b) - calculateWeight(a); + if (weightDifference !== 0) { + return weightDifference; + } + // if weight is the same, sort by name + if (a.name === null) return 1; + if (b.name === null) return -1; + return a.name.localeCompare(b.name); + }); + }, [members]); }