From 3061bd557e34a7233e937e6735efb412553670de Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Thu, 6 Jun 2024 18:58:02 -0700 Subject: [PATCH 1/7] Pathfinder experiments --- src/app/bungie-api/destiny2-api.ts | 2 +- src/app/progress/Progress.tsx | 20 ++++++++++++++++++++ src/app/progress/SeasonalChallenges.tsx | 2 +- src/app/records/presentation-nodes.ts | 16 +++++++++++++++- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/app/bungie-api/destiny2-api.ts b/src/app/bungie-api/destiny2-api.ts index 6ebf36a4be..a11ddf0708 100644 --- a/src/app/bungie-api/destiny2-api.ts +++ b/src/app/bungie-api/destiny2-api.ts @@ -103,7 +103,7 @@ export function getStores(platform: DestinyAccount): Promise )} + {pathfinderPresentationNode && ( + + + + )} + {pathfinderPresentationNode2 && ( + + + + )} + diff --git a/src/app/progress/SeasonalChallenges.tsx b/src/app/progress/SeasonalChallenges.tsx index 54404227ab..a104469048 100644 --- a/src/app/progress/SeasonalChallenges.tsx +++ b/src/app/progress/SeasonalChallenges.tsx @@ -38,7 +38,7 @@ export default function SeasonalChallenges({ // Don't show records that have been redeemed const state = r.recordComponent.state; const acquired = Boolean(state & DestinyRecordState.RecordRedeemed); - return !acquired; + return !acquired && !(state & DestinyRecordState.RewardUnavailable); }) .map((r) => recordToPursuitItem( diff --git a/src/app/records/presentation-nodes.ts b/src/app/records/presentation-nodes.ts index 7e8314e288..b948ff0da2 100644 --- a/src/app/records/presentation-nodes.ts +++ b/src/app/records/presentation-nodes.ts @@ -15,10 +15,12 @@ import { DestinyMetricComponent, DestinyMetricDefinition, DestinyPresentationNodeCollectibleChildEntry, + DestinyPresentationNodeComponent, DestinyPresentationNodeCraftableChildEntry, DestinyPresentationNodeDefinition, DestinyPresentationNodeMetricChildEntry, DestinyPresentationNodeRecordChildEntry, + DestinyPresentationNodeState, DestinyProfileResponse, DestinyRecordComponent, DestinyRecordDefinition, @@ -43,6 +45,7 @@ export interface DimPresentationNode extends DimPresentationNodeLeaf { * or generated with fake info. */ nodeDef: DestinyPresentationNodeDefinition | undefined; + nodeComp: DestinyPresentationNodeComponent | undefined; /** May or may not be an actual hash */ hash: number; name: string; @@ -110,6 +113,12 @@ export function toPresentationNodeTree( if (presentationNodeDef.redacted) { return null; } + if ( + (profileResponse.profilePresentationNodes.data?.nodes[presentationNodeDef.hash]?.state ?? 0) & + DestinyPresentationNodeState.Invisible + ) { + return null; + } // For titles, display the title, completion and gilding count const titleInfo = @@ -117,7 +126,7 @@ export function toPresentationNodeTree( ? getTitleInfo( presentationNodeDef.completionRecordHash, defs, - itemCreationContext.profileResponse.profileRecords.data, + profileResponse.profileRecords.data, genderHash, ) : undefined; @@ -128,7 +137,11 @@ export function toPresentationNodeTree( name: titleInfo?.title || presentationNodeDef.displayProperties.name, icon: presentationNodeDef.displayProperties.icon, titleInfo, + nodeComp: profileResponse.profilePresentationNodes.data?.nodes[presentationNodeDef.hash], }; + if (presentationNodeDef.parentNodeHashes[0] === 1062988660) { + console.log(presentationNodeDef, commonNodeProperties); + } if (presentationNodeDef.children.collectibles?.length) { const collectibles = toCollectibles( itemCreationContext, @@ -250,6 +263,7 @@ function buildPlugSetPresentationNode( visible: plugSetItems.length, acquired, plugs: plugEntries, + nodeComp: undefined, }; return subnode; } From e55e0e8dffcc2054a6a218c66bd1c93b41133a94 Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Tue, 18 Jun 2024 00:23:20 -0700 Subject: [PATCH 2/7] Fair bit of progress --- config/i18n.json | 2 + src/app/progress/Milestones.tsx | 6 +- src/app/progress/Pathfinder.m.scss | 27 ++++++++ src/app/progress/Pathfinder.m.scss.d.ts | 8 +++ src/app/progress/Pathfinder.tsx | 83 +++++++++++++++++++++++++ src/app/progress/Progress.tsx | 56 ++++++++++------- src/app/progress/Pursuit.tsx | 32 ++++------ src/app/progress/PursuitItem.m.scss | 6 ++ src/app/progress/PursuitItem.tsx | 2 +- src/app/progress/Pursuits.tsx | 3 - src/app/progress/SeasonalChallenges.tsx | 2 +- src/app/progress/milestone-items.ts | 4 +- src/app/records/presentation-nodes.ts | 9 +-- src/locale/en.json | 2 + 14 files changed, 184 insertions(+), 58 deletions(-) create mode 100644 src/app/progress/Pathfinder.m.scss create mode 100644 src/app/progress/Pathfinder.m.scss.d.ts create mode 100644 src/app/progress/Pathfinder.tsx diff --git a/config/i18n.json b/config/i18n.json index 3f0da51e86..a810073819 100644 --- a/config/i18n.json +++ b/config/i18n.json @@ -1087,6 +1087,7 @@ "CrucibleRank": "Ranks", "Items": "Quest Items", "Milestones": "Milestones & Challenges", + "PaleHeartPathfinder": "Pale Heart Pathfinder", "PercentPrestige": "{{pct}}% to reset", "PointsUsed": "1 point used", "PointsUsed_plural": "{{count}} points used", @@ -1100,6 +1101,7 @@ "RecordValue": "{{value}}pts", "Resets": "1 reset", "Resets_plural": "{{count}} resets", + "RitualPathfinder": "Ritual Pathfinder", "SecretTriumph": "Secret Triumph", "StatTrackers": "Stat Trackers", "TrackedTriumphs": "Tracked Triumphs", diff --git a/src/app/progress/Milestones.tsx b/src/app/progress/Milestones.tsx index bd9cce882f..1fb230132e 100644 --- a/src/app/progress/Milestones.tsx +++ b/src/app/progress/Milestones.tsx @@ -21,6 +21,8 @@ import { getEngramPowerBonus } from './engrams'; import { milestoneToItems } from './milestone-items'; import { getCharacterProgressions } from './selectors'; +const sortPowerBonus = compareBy((powerBonus: number | undefined) => -(powerBonus ?? -1)); + /** * The list of Milestones for a character. Milestones are different from pursuits and * represent challenges, story prompts, and other stuff you can do not represented by Pursuits. @@ -62,8 +64,6 @@ export default function Milestones({ } }); - const sortPowerBonus = compareBy((powerBonus: number | undefined) => -(powerBonus ?? -1)); - return ( <> {characterProgressions && ( @@ -84,7 +84,7 @@ export default function Milestones({ )} {[...milestonesByPower.keys()].sort(sortPowerBonus).map((powerBonus) => ( -
+

{powerBonus === undefined ? t('Progress.PowerBonusHeaderUndefined') diff --git a/src/app/progress/Pathfinder.m.scss b/src/app/progress/Pathfinder.m.scss new file mode 100644 index 0000000000..66e50c3a0c --- /dev/null +++ b/src/app/progress/Pathfinder.m.scss @@ -0,0 +1,27 @@ +.pathfinderRow { + /* + display: grid; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + grid-auto-rows: min-content; + gap: 24px 16px; + margin: 16px 0; + box-sizing: border-box; + */ + composes: flexWrap from '../dim-ui/common.m.scss'; + box-sizing: border-box; + margin: 16px 0; + justify-content: center; + gap: 24px 16px; + + > * { + flex: 1; + max-width: 250px; + min-width: 150px; + } +} + +.divider { + opacity: 0.3; + border: 0; + border-bottom: 1px solid white; +} diff --git a/src/app/progress/Pathfinder.m.scss.d.ts b/src/app/progress/Pathfinder.m.scss.d.ts new file mode 100644 index 0000000000..87417ecdf0 --- /dev/null +++ b/src/app/progress/Pathfinder.m.scss.d.ts @@ -0,0 +1,8 @@ +// This file is automatically generated. +// Please do not change this file! +interface CssExports { + 'divider': string; + 'pathfinderRow': string; +} +export const cssExports: CssExports; +export default cssExports; diff --git a/src/app/progress/Pathfinder.tsx b/src/app/progress/Pathfinder.tsx new file mode 100644 index 0000000000..f0360029ba --- /dev/null +++ b/src/app/progress/Pathfinder.tsx @@ -0,0 +1,83 @@ +import { trackedTriumphsSelector } from 'app/dim-api/selectors'; +import CollapsibleTitle from 'app/dim-ui/CollapsibleTitle'; +import { DimItem } from 'app/inventory/item-types'; +import { createItemContextSelector } from 'app/inventory/selectors'; +import { DimStore } from 'app/inventory/store-types'; +import { toPresentationNodeTree } from 'app/records/presentation-nodes'; +import { addDividers } from 'app/utils/react'; +import { DestinyPresentationNodeDefinition, DestinyRecordState } from 'bungie-api-ts/destiny2'; +import { useSelector } from 'react-redux'; +import styles from './Pathfinder.m.scss'; +import Pursuit from './Pursuit'; +import { recordToPursuitItem } from './milestone-items'; + +/** + * List out all the seasonal challenges for the character, grouped out in a useful way. + */ +export default function Pathfinder({ + id, + name, + presentationNode, + store, +}: { + id: string; + name: string; + presentationNode: DestinyPresentationNodeDefinition; + store: DimStore; +}) { + const itemCreationContext = useSelector(createItemContextSelector); + const nodeTree = toPresentationNodeTree(itemCreationContext, presentationNode.hash); + + const allRecords = nodeTree?.childPresentationNodes?.[0]?.records?.toReversed() ?? []; + console.log(name, { nodeTree, allRecords }); + + const trackedRecords = useSelector(trackedTriumphsSelector); + + const acquiredRecords = new Set(); + + const pursuits = allRecords + .filter((r) => { + // Don't show records that have been redeemed + const state = r.recordComponent.state; + const acquired = Boolean(state & DestinyRecordState.RecordRedeemed); + if (acquired) { + acquiredRecords.add(r.recordDef.hash); + } + return true /* !acquired */ /* && !(state & DestinyRecordState.RewardUnavailable) */; + }) + .map((r) => + recordToPursuitItem( + r, + itemCreationContext.buckets, + store, + presentationNode.displayProperties.name, + trackedRecords.includes(r.recordDef.hash), + ), + ); + + const pursuitGroups: DimItem[][] = []; + for (let i = 6; i > 0; i--) { + pursuitGroups.push(pursuits.splice(0, i)); + } + + return ( +
+ + {addDividers( + pursuitGroups.map((pursuits) => ( +
+ {pursuits.map((item) => ( + + ))} +
+ )), +
, + )} +
+
+ ); +} diff --git a/src/app/progress/Progress.tsx b/src/app/progress/Progress.tsx index aff3fe4bea..43383c7177 100644 --- a/src/app/progress/Progress.tsx +++ b/src/app/progress/Progress.tsx @@ -14,6 +14,7 @@ import { RAID_NODE } from 'app/search/d2-known-values'; import { querySelector, useIsPhonePortrait } from 'app/shell/selectors'; import { usePageTitle } from 'app/utils/hooks'; import { PanInfo, motion } from 'framer-motion'; +import _ from 'lodash'; import { useState } from 'react'; import { useSelector } from 'react-redux'; import { DestinyAccount } from '../accounts/destiny-account'; @@ -21,6 +22,7 @@ import CollapsibleTitle from '../dim-ui/CollapsibleTitle'; import ErrorBoundary from '../dim-ui/ErrorBoundary'; import { Event } from './Event'; import Milestones from './Milestones'; +import Pathfinder from './Pathfinder'; import styles from './Progress.m.scss'; import Pursuits from './Pursuits'; import Raids from './Raids'; @@ -89,27 +91,28 @@ export default function Progress({ account }: { account: DestinyAccount }) { coreSettings?.seasonalChallengesPresentationNodeHash !== undefined && defs.PresentationNode.get(coreSettings.seasonalChallengesPresentationNodeHash); - const pathfinderPresentationNode = defs.PresentationNode.get(1062988660); + const paleHeartPathfinderNode = defs.PresentationNode.get(1062988660); + const ritualsPathfinderNode = defs.PresentationNode.get(622609416); - const pathfinderPresentationNode2 = defs.PresentationNode.get(622609416); - const menuItems = [ + const menuItems = _.compact([ { id: 'ranks', title: t('Progress.CrucibleRank') }, { id: 'trackedTriumphs', title: t('Progress.TrackedTriumphs') }, - ...(eventCard ? [{ id: 'event', title: eventCard.displayProperties.name }] : []), + eventCard && { id: 'event', title: eventCard.displayProperties.name }, { id: 'milestones', title: t('Progress.Milestones') }, - ...(seasonalChallengesPresentationNode - ? [ - { - id: 'seasonal-challenges', - title: seasonalChallengesPresentationNode.displayProperties.name, - }, - ] - : []), + paleHeartPathfinderNode && { + id: 'paleHeartPathfinder', + title: t('Progress.PaleHeartPathfinder'), + }, + ritualsPathfinderNode && { id: 'ritualPathfinder', title: t('Progress.RitualPathfinder') }, + seasonalChallengesPresentationNode && { + id: 'seasonal-challenges', + title: seasonalChallengesPresentationNode.displayProperties.name, + }, { id: 'Bounties', title: t('Progress.Bounties') }, { id: 'Quests', title: t('Progress.Quests') }, { id: 'Items', title: t('Progress.Items') }, - ...(raidNode ? [{ id: 'raids', title: raidTitle }] : []), - ]; + raidNode && { id: 'raids', title: raidTitle }, + ]); return ( @@ -177,27 +180,32 @@ export default function Progress({ account }: { account: DestinyAccount }) { - {seasonalChallengesPresentationNode && ( - - + )} - {pathfinderPresentationNode && ( - - + )} - {pathfinderPresentationNode2 && ( + + {seasonalChallengesPresentationNode && ( diff --git a/src/app/progress/Pursuit.tsx b/src/app/progress/Pursuit.tsx index 4c298a0f3c..645b5facb7 100644 --- a/src/app/progress/Pursuit.tsx +++ b/src/app/progress/Pursuit.tsx @@ -13,22 +13,17 @@ import { useSelector } from 'react-redux'; import { ObjectiveValue } from './Objective'; import PursuitItem from './PursuitItem'; -// Props provided from parents -interface Props { - item: DimItem; - hideDescription?: boolean; - searchHidden?: boolean; -} - /** * A Pursuit is an inventory item that represents a bounty or quest. This displays * a pursuit tile for the Progress page. */ export default function Pursuit({ item, - hideDescription, searchHidden: alreadySearchHidden, -}: Props) { +}: { + item: DimItem; + searchHidden?: boolean; +}) { const defs = useD2Definitions()!; const isNew = useSelector(isNewSelector(item)); const searchHidden = useSelector( @@ -73,17 +68,16 @@ export default function Pursuit({ )}

- {!hideDescription && ( -
- - - {item.name} - -
- -
+ +
+ + + {item.name} + +
+
- )} +
)} diff --git a/src/app/progress/PursuitItem.m.scss b/src/app/progress/PursuitItem.m.scss index bf7cde474a..fa155ba384 100644 --- a/src/app/progress/PursuitItem.m.scss +++ b/src/app/progress/PursuitItem.m.scss @@ -10,6 +10,7 @@ box-sizing: border-box; cursor: pointer; + :global(.pathfinder) &, :global(#milestones) &, :global(#seasonal-challenges) & { height: calc(var(--item-size) * 10 / 9 + 4px); @@ -41,6 +42,11 @@ outline: none; } + :global(.pathfinder) & { + border-radius: 50%; + padding: 4px; + } + :global(#milestones) &, :global(#event) &, :global(#seasonal-challenges) & { diff --git a/src/app/progress/PursuitItem.tsx b/src/app/progress/PursuitItem.tsx index 9dcfbd3ca5..b706425a3c 100644 --- a/src/app/progress/PursuitItem.tsx +++ b/src/app/progress/PursuitItem.tsx @@ -100,7 +100,7 @@ export function StackAmount({ amount, full }: { amount: number; full?: boolean } [styles.fullstack]: full, })} > - {amount} + {amount.toLocaleString()}
); } diff --git a/src/app/progress/Pursuits.tsx b/src/app/progress/Pursuits.tsx index 5100103a17..2f9c277399 100644 --- a/src/app/progress/Pursuits.tsx +++ b/src/app/progress/Pursuits.tsx @@ -77,13 +77,11 @@ export function PursuitsGroup({ defs, store, pursuits, - hideDescriptions, pursuitsInfo = pursuitsInfoFile, }: { defs: D2ManifestDefinitions; store: DimStore; pursuits: DimItem[]; - hideDescriptions?: boolean; pursuitsInfo?: { [hash: string]: { [type in DefType]?: number[] } }; }) { const [bountyFilters, setBountyFilters] = useState([]); @@ -103,7 +101,6 @@ export function PursuitsGroup({ item={item} key={item.index} searchHidden={!matchBountyFilters(defs, item, bountyFilters, pursuitsInfo)} - hideDescription={hideDescriptions} /> ))} diff --git a/src/app/progress/SeasonalChallenges.tsx b/src/app/progress/SeasonalChallenges.tsx index a104469048..54404227ab 100644 --- a/src/app/progress/SeasonalChallenges.tsx +++ b/src/app/progress/SeasonalChallenges.tsx @@ -38,7 +38,7 @@ export default function SeasonalChallenges({ // Don't show records that have been redeemed const state = r.recordComponent.state; const acquired = Boolean(state & DestinyRecordState.RecordRedeemed); - return !acquired && !(state & DestinyRecordState.RewardUnavailable); + return !acquired; }) .map((r) => recordToPursuitItem( diff --git a/src/app/progress/milestone-items.ts b/src/app/progress/milestone-items.ts index 05c7b9d37f..8d8a380c0e 100644 --- a/src/app/progress/milestone-items.ts +++ b/src/app/progress/milestone-items.ts @@ -385,7 +385,9 @@ export function recordToPursuitItem( }; if (record.recordDef.rewardItems) { - dimItem.pursuit.rewards = record.recordDef.rewardItems; + dimItem.pursuit.rewards = record.recordDef.rewardItems.filter( + (_r, i) => record.recordComponent.rewardVisibilty?.[i] ?? true, + ); } dimItem.trackable = true; diff --git a/src/app/records/presentation-nodes.ts b/src/app/records/presentation-nodes.ts index b948ff0da2..409685bbce 100644 --- a/src/app/records/presentation-nodes.ts +++ b/src/app/records/presentation-nodes.ts @@ -45,7 +45,7 @@ export interface DimPresentationNode extends DimPresentationNodeLeaf { * or generated with fake info. */ nodeDef: DestinyPresentationNodeDefinition | undefined; - nodeComp: DestinyPresentationNodeComponent | undefined; + nodeComponent: DestinyPresentationNodeComponent | undefined; /** May or may not be an actual hash */ hash: number; name: string; @@ -137,11 +137,8 @@ export function toPresentationNodeTree( name: titleInfo?.title || presentationNodeDef.displayProperties.name, icon: presentationNodeDef.displayProperties.icon, titleInfo, - nodeComp: profileResponse.profilePresentationNodes.data?.nodes[presentationNodeDef.hash], + nodeComponent: profileResponse.profilePresentationNodes.data?.nodes[presentationNodeDef.hash], }; - if (presentationNodeDef.parentNodeHashes[0] === 1062988660) { - console.log(presentationNodeDef, commonNodeProperties); - } if (presentationNodeDef.children.collectibles?.length) { const collectibles = toCollectibles( itemCreationContext, @@ -263,7 +260,7 @@ function buildPlugSetPresentationNode( visible: plugSetItems.length, acquired, plugs: plugEntries, - nodeComp: undefined, + nodeComponent: undefined, }; return subnode; } diff --git a/src/locale/en.json b/src/locale/en.json index ac5b55bc3e..eaca840d67 100644 --- a/src/locale/en.json +++ b/src/locale/en.json @@ -1079,6 +1079,7 @@ "Milestones": "Milestones & Challenges", "NoEventChallenges": "You have completed all event challenges", "NoTrackedTriumph": "You have no tracked triumphs. Track as many as you like in DIM.", + "PaleHeartPathfinder": "Pale Heart Pathfinder", "PercentPrestige": "{{pct}}% to reset", "PointsUsed": "1 point used", "PointsUsed_plural": "{{count}} points used", @@ -1093,6 +1094,7 @@ "RecordValue": "{{value}}pts", "Resets": "1 reset", "Resets_plural": "{{count}} resets", + "RitualPathfinder": "Ritual Pathfinder", "SecretTriumph": "Secret Triumph", "StatTrackers": "Stat Trackers", "TrackedTriumphs": "Tracked Triumphs" From f4b5d6d3123a4643c51b3c09a76420895460bf3e Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Tue, 18 Jun 2024 00:50:16 -0700 Subject: [PATCH 3/7] Looking good --- src/app/item-popup/ItemPopupHeader.m.scss | 4 +++ src/app/progress/Pathfinder.m.scss | 41 +++++++++++++++++------ src/app/progress/Pathfinder.m.scss.d.ts | 1 + src/app/progress/Pathfinder.tsx | 6 +++- src/app/progress/Pursuit.tsx | 4 ++- 5 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/app/item-popup/ItemPopupHeader.m.scss b/src/app/item-popup/ItemPopupHeader.m.scss index 3062b8ddda..5642ecfb47 100644 --- a/src/app/item-popup/ItemPopupHeader.m.scss +++ b/src/app/item-popup/ItemPopupHeader.m.scss @@ -32,6 +32,10 @@ text-decoration: none; margin: 0 !important; padding: 0; + + @include phone-portrait { + margin: 0 32px 0 0 !important; + } } .subtitle { diff --git a/src/app/progress/Pathfinder.m.scss b/src/app/progress/Pathfinder.m.scss index 66e50c3a0c..ef477ea187 100644 --- a/src/app/progress/Pathfinder.m.scss +++ b/src/app/progress/Pathfinder.m.scss @@ -1,12 +1,6 @@ +@use '../variables.scss' as *; + .pathfinderRow { - /* - display: grid; - grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); - grid-auto-rows: min-content; - gap: 24px 16px; - margin: 16px 0; - box-sizing: border-box; - */ composes: flexWrap from '../dim-ui/common.m.scss'; box-sizing: border-box; margin: 16px 0; @@ -18,10 +12,37 @@ max-width: 250px; min-width: 150px; } + + @media (max-width: 1270px) { + margin: 8px 10px; + gap: 14px; + width: auto; + + > * { + flex: 0; + width: var(--item-size); + min-width: var(--item-size); + } + + :global(.milestone-icon) { + margin: 0; + } + :global(.milestone-info) { + display: none; + } + } } .divider { - opacity: 0.3; border: 0; - border-bottom: 1px solid white; + border-bottom: 1px solid var(--theme-button-bg); + margin: 0; +} + +.completed { + :global(.milestone-icon) img { + border-color: $xp; + border-width: 2px; + padding: 3px; + } } diff --git a/src/app/progress/Pathfinder.m.scss.d.ts b/src/app/progress/Pathfinder.m.scss.d.ts index 87417ecdf0..76fd5d43f1 100644 --- a/src/app/progress/Pathfinder.m.scss.d.ts +++ b/src/app/progress/Pathfinder.m.scss.d.ts @@ -1,6 +1,7 @@ // This file is automatically generated. // Please do not change this file! interface CssExports { + 'completed': string; 'divider': string; 'pathfinderRow': string; } diff --git a/src/app/progress/Pathfinder.tsx b/src/app/progress/Pathfinder.tsx index f0360029ba..fe3cc7aca5 100644 --- a/src/app/progress/Pathfinder.tsx +++ b/src/app/progress/Pathfinder.tsx @@ -70,7 +70,11 @@ export default function Pathfinder({ ))}
diff --git a/src/app/progress/Pursuit.tsx b/src/app/progress/Pursuit.tsx index 645b5facb7..ec72b9b44f 100644 --- a/src/app/progress/Pursuit.tsx +++ b/src/app/progress/Pursuit.tsx @@ -20,9 +20,11 @@ import PursuitItem from './PursuitItem'; export default function Pursuit({ item, searchHidden: alreadySearchHidden, + className, }: { item: DimItem; searchHidden?: boolean; + className?: string; }) { const defs = useD2Definitions()!; const isNew = useSelector(isNewSelector(item)); @@ -48,7 +50,7 @@ export default function Pursuit({ {(ref, onClick) => (