perf(renderer): cache repeated team badge selectors
This commit is contained in:
parent
93a45e0823
commit
5041c79916
3 changed files with 35 additions and 1 deletions
|
|
@ -210,12 +210,14 @@ interface SidebarTeamsDerived {
|
||||||
}
|
}
|
||||||
|
|
||||||
let cachedSidebarTeamsSignature: string | null = null;
|
let cachedSidebarTeamsSignature: string | null = null;
|
||||||
|
let cachedSidebarTeamsSource: readonly TeamSummary[] | null = null;
|
||||||
let cachedSidebarTeamsDerived: SidebarTeamsDerived = {
|
let cachedSidebarTeamsDerived: SidebarTeamsDerived = {
|
||||||
identityKey: '',
|
identityKey: '',
|
||||||
filterTeams: [],
|
filterTeams: [],
|
||||||
statusSummaries: [],
|
statusSummaries: [],
|
||||||
memberColorByTeam: new Map(),
|
memberColorByTeam: new Map(),
|
||||||
};
|
};
|
||||||
|
let cachedLeadOfflineTeamsSource: Partial<Record<string, LeadActivityState>> | null = null;
|
||||||
let cachedLeadOfflineTeamsSignature = '';
|
let cachedLeadOfflineTeamsSignature = '';
|
||||||
let cachedLeadOfflineTeamNames: string[] = [];
|
let cachedLeadOfflineTeamNames: string[] = [];
|
||||||
|
|
||||||
|
|
@ -255,6 +257,10 @@ function buildTeamNamesIdentityKey(teams: readonly TeamSummary[]): string {
|
||||||
function selectLeadOfflineTeamNames(
|
function selectLeadOfflineTeamNames(
|
||||||
leadActivityByTeam: Partial<Record<string, LeadActivityState>>
|
leadActivityByTeam: Partial<Record<string, LeadActivityState>>
|
||||||
): string[] {
|
): string[] {
|
||||||
|
if (leadActivityByTeam === cachedLeadOfflineTeamsSource) {
|
||||||
|
return cachedLeadOfflineTeamNames;
|
||||||
|
}
|
||||||
|
|
||||||
const offlineTeamNames: string[] = [];
|
const offlineTeamNames: string[] = [];
|
||||||
for (const [teamName, activity] of Object.entries(leadActivityByTeam)) {
|
for (const [teamName, activity] of Object.entries(leadActivityByTeam)) {
|
||||||
if (activity === 'offline') {
|
if (activity === 'offline') {
|
||||||
|
|
@ -269,17 +275,24 @@ function selectLeadOfflineTeamNames(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signature === cachedLeadOfflineTeamsSignature) {
|
if (signature === cachedLeadOfflineTeamsSignature) {
|
||||||
|
cachedLeadOfflineTeamsSource = leadActivityByTeam;
|
||||||
return cachedLeadOfflineTeamNames;
|
return cachedLeadOfflineTeamNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cachedLeadOfflineTeamsSource = leadActivityByTeam;
|
||||||
cachedLeadOfflineTeamsSignature = signature;
|
cachedLeadOfflineTeamsSignature = signature;
|
||||||
cachedLeadOfflineTeamNames = offlineTeamNames;
|
cachedLeadOfflineTeamNames = offlineTeamNames;
|
||||||
return cachedLeadOfflineTeamNames;
|
return cachedLeadOfflineTeamNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectSidebarTeamsDerived(teams: readonly TeamSummary[]): SidebarTeamsDerived {
|
function selectSidebarTeamsDerived(teams: readonly TeamSummary[]): SidebarTeamsDerived {
|
||||||
|
if (teams === cachedSidebarTeamsSource) {
|
||||||
|
return cachedSidebarTeamsDerived;
|
||||||
|
}
|
||||||
|
|
||||||
const signature = buildSidebarTeamsSignature(teams);
|
const signature = buildSidebarTeamsSignature(teams);
|
||||||
if (signature === cachedSidebarTeamsSignature) {
|
if (signature === cachedSidebarTeamsSignature) {
|
||||||
|
cachedSidebarTeamsSource = teams;
|
||||||
return cachedSidebarTeamsDerived;
|
return cachedSidebarTeamsDerived;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -290,6 +303,7 @@ function selectSidebarTeamsDerived(teams: readonly TeamSummary[]): SidebarTeamsD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cachedSidebarTeamsSource = teams;
|
||||||
cachedSidebarTeamsSignature = signature;
|
cachedSidebarTeamsSignature = signature;
|
||||||
cachedSidebarTeamsDerived = {
|
cachedSidebarTeamsDerived = {
|
||||||
identityKey: buildTeamNamesIdentityKey(teams),
|
identityKey: buildTeamNamesIdentityKey(teams),
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,18 @@ interface MemberBadgeProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const EMPTY_TEAM_MEMBERS: readonly ResolvedTeamMember[] = [];
|
const EMPTY_TEAM_MEMBERS: readonly ResolvedTeamMember[] = [];
|
||||||
|
const memberAvatarMapCache = new WeakMap<readonly ResolvedTeamMember[], Map<string, string>>();
|
||||||
|
|
||||||
|
function getCachedMemberAvatarMap(members: readonly ResolvedTeamMember[]): Map<string, string> {
|
||||||
|
const cached = memberAvatarMapCache.get(members);
|
||||||
|
if (cached) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
const next = buildMemberAvatarMap(members);
|
||||||
|
memberAvatarMapCache.set(members, next);
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reusable member avatar + colored name badge.
|
* Reusable member avatar + colored name badge.
|
||||||
|
|
@ -61,7 +73,7 @@ export const MemberBadge = memo(
|
||||||
? selectResolvedMembersForTeamName(s, effectiveAvatarTeamName)
|
? selectResolvedMembersForTeamName(s, effectiveAvatarTeamName)
|
||||||
: EMPTY_TEAM_MEMBERS
|
: EMPTY_TEAM_MEMBERS
|
||||||
);
|
);
|
||||||
const avatarMap = useMemo(() => buildMemberAvatarMap(teamMembers), [teamMembers]);
|
const avatarMap = useMemo(() => getCachedMemberAvatarMap(teamMembers), [teamMembers]);
|
||||||
const avatarSize = size === 'md' ? 32 : size === 'sm' ? 24 : 18;
|
const avatarSize = size === 'md' ? 32 : size === 'sm' ? 24 : 18;
|
||||||
const avatarClass = size === 'md' ? 'size-6' : size === 'sm' ? 'size-5' : 'size-4';
|
const avatarClass = size === 'md' ? 'size-6' : size === 'sm' ? 'size-5' : 'size-4';
|
||||||
const textClass = size === 'md' ? 'text-xs' : size === 'sm' ? 'text-[10px]' : 'text-[9px]';
|
const textClass = size === 'md' ? 'text-xs' : size === 'sm' ? 'text-[10px]' : 'text-[9px]';
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ interface TeamMentionEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
let cachedTeamMentionSignature = '';
|
let cachedTeamMentionSignature = '';
|
||||||
|
let cachedTeamMentionSource: readonly TeamSummary[] | null = null;
|
||||||
let cachedTeamMentionMeta: TeamMentionMeta = {
|
let cachedTeamMentionMeta: TeamMentionMeta = {
|
||||||
teamNames: EMPTY_TEAM_NAMES,
|
teamNames: EMPTY_TEAM_NAMES,
|
||||||
teamColorByName: EMPTY_TEAM_COLOR_MAP,
|
teamColorByName: EMPTY_TEAM_COLOR_MAP,
|
||||||
|
|
@ -142,8 +143,13 @@ function getTeamMentionSignature(teams: readonly TeamSummary[]): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectMessagesPanelTeamMentionMeta(teams: readonly TeamSummary[]): TeamMentionMeta {
|
function selectMessagesPanelTeamMentionMeta(teams: readonly TeamSummary[]): TeamMentionMeta {
|
||||||
|
if (teams === cachedTeamMentionSource) {
|
||||||
|
return cachedTeamMentionMeta;
|
||||||
|
}
|
||||||
|
|
||||||
const signature = getTeamMentionSignature(teams);
|
const signature = getTeamMentionSignature(teams);
|
||||||
if (signature === cachedTeamMentionSignature) {
|
if (signature === cachedTeamMentionSignature) {
|
||||||
|
cachedTeamMentionSource = teams;
|
||||||
return cachedTeamMentionMeta;
|
return cachedTeamMentionMeta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,6 +163,7 @@ function selectMessagesPanelTeamMentionMeta(teams: readonly TeamSummary[]): Team
|
||||||
.sort(compareTeamMentionEntries);
|
.sort(compareTeamMentionEntries);
|
||||||
|
|
||||||
if (entries.length === 0) {
|
if (entries.length === 0) {
|
||||||
|
cachedTeamMentionSource = teams;
|
||||||
cachedTeamMentionSignature = signature;
|
cachedTeamMentionSignature = signature;
|
||||||
cachedTeamMentionMeta = {
|
cachedTeamMentionMeta = {
|
||||||
teamNames: EMPTY_TEAM_NAMES,
|
teamNames: EMPTY_TEAM_NAMES,
|
||||||
|
|
@ -180,6 +187,7 @@ function selectMessagesPanelTeamMentionMeta(teams: readonly TeamSummary[]): Team
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cachedTeamMentionSource = teams;
|
||||||
cachedTeamMentionSignature = signature;
|
cachedTeamMentionSignature = signature;
|
||||||
cachedTeamMentionMeta = { teamNames, teamColorByName };
|
cachedTeamMentionMeta = { teamNames, teamColorByName };
|
||||||
return cachedTeamMentionMeta;
|
return cachedTeamMentionMeta;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue