From 8c2104c2de66fa02941893e6cd4d7e628f1588db Mon Sep 17 00:00:00 2001 From: robojumper Date: Fri, 7 Jan 2022 18:35:36 +0100 Subject: [PATCH] Use Item Tooltip everywhere item cannot be popped --- src/app/dim-ui/PressTip.tsx | 34 ++++++++++------ src/app/infuse/InfusionFinder.tsx | 16 ++++++-- src/app/inventory/InventoryItem.tsx | 10 ++--- src/app/inventory/ItemTooltip.m.scss | 22 ++++++++++- src/app/inventory/ItemTooltip.m.scss.d.ts | 4 ++ src/app/inventory/ItemTooltip.tsx | 47 ++++++++++++++++------- src/app/inventory/StoreInventoryItem.tsx | 4 ++ 7 files changed, 103 insertions(+), 34 deletions(-) diff --git a/src/app/dim-ui/PressTip.tsx b/src/app/dim-ui/PressTip.tsx index 5df8b232dc..c23b98c2e6 100644 --- a/src/app/dim-ui/PressTip.tsx +++ b/src/app/dim-ui/PressTip.tsx @@ -29,6 +29,10 @@ interface Props { * constructing the tree until the tooltip is shown. */ tooltip: React.ReactNode | (() => React.ReactNode); + /** + * Whether the presstip should be shown or not. + */ + disabled?: boolean; /** * The children of this component define the content that will trigger the tooltip. */ @@ -41,6 +45,7 @@ interface Props { type ControlProps = Props & React.HTMLAttributes & { + events: React.HTMLAttributes; open: boolean; triggerRef: React.RefObject; }; @@ -65,10 +70,12 @@ type ControlProps = Props & function Control({ tooltip, open, + disabled, triggerRef, children, elementType: Component = 'div', className, + events, ...rest }: ControlProps) { const tooltipContents = useRef(null); @@ -94,8 +101,10 @@ function Control({ // TODO: or use framer motion layout animations? return ( - {children} +
{children}
{open && + !disabled && + tooltip && ReactDOM.createPortal(
{_.isFunction(tooltip) ? tooltip() : tooltip}
@@ -142,14 +151,17 @@ function PressTip(props: Props) { timer.current = 0; }, []); - const hover = useCallback((e: React.MouseEvent | React.TouchEvent | TouchEvent) => { - e.preventDefault(); - clearTimeout(timer.current); - timer.current = window.setTimeout(() => { - setOpen(true); - }, hoverDelay); - touchStartTime.current = performance.now(); - }, []); + const hover = useCallback( + (e: React.MouseEvent | React.TouchEvent | TouchEvent) => { + e.preventDefault(); + clearTimeout(timer.current); + timer.current = window.setTimeout(() => { + setOpen(!props.disabled); + }, hoverDelay); + touchStartTime.current = performance.now(); + }, + [props.disabled] + ); // Stop the hover timer when the component unmounts useEffect(() => () => clearTimeout(timer.current), []); @@ -181,12 +193,12 @@ function PressTip(props: Props) { onClick: absorbClick, } : { - onMouseEnter: hover, + onMouseOver: hover, onMouseUp: closeToolTip, onMouseLeave: closeToolTip, }; - return ; + return ; } export default PressTip; diff --git a/src/app/infuse/InfusionFinder.tsx b/src/app/infuse/InfusionFinder.tsx index 6132caf60a..d2364f4834 100644 --- a/src/app/infuse/InfusionFinder.tsx +++ b/src/app/infuse/InfusionFinder.tsx @@ -229,15 +229,23 @@ export default function InfusionFinder() {
- {effectiveTarget ? : missingItem} + {effectiveTarget ? ( + + ) : ( + missingItem + )}
- {effectiveSource ? : missingItem} + {effectiveSource ? ( + + ) : ( + missingItem + )}
- {result ? : missingItem} + {result ? : missingItem}
); diff --git a/src/app/inventory/InventoryItem.tsx b/src/app/inventory/InventoryItem.tsx index 4f6a97fb99..22fb083cf6 100644 --- a/src/app/inventory/InventoryItem.tsx +++ b/src/app/inventory/InventoryItem.tsx @@ -134,9 +134,9 @@ export default function InventoryItem({
); - if (tooltip) { - return }>{inner}; - } else { - return inner; - } + return ( + }> + {inner} + + ); } diff --git a/src/app/inventory/ItemTooltip.m.scss b/src/app/inventory/ItemTooltip.m.scss index b3252d5a7a..015545dd89 100644 --- a/src/app/inventory/ItemTooltip.m.scss +++ b/src/app/inventory/ItemTooltip.m.scss @@ -5,6 +5,9 @@ flex-flow: column; margin: 4px 0; + border-left: 2px solid #888; + padding-left: 3px; + > div { display: flex; flex-flow: row; @@ -17,9 +20,26 @@ } } +.perkSelected { + font-weight: bold; +} + +.notes { + margin-left: 4px; +} + +.note { + margin-left: -4px; +} + +.noteIcon { + height: 24px; + width: 24px; +} + .stats { margin: 4px 0 0 0; :global(.stat) { - line-height: 8px; + line-height: 12px; } } diff --git a/src/app/inventory/ItemTooltip.m.scss.d.ts b/src/app/inventory/ItemTooltip.m.scss.d.ts index b2bcb7cdd4..23027153be 100644 --- a/src/app/inventory/ItemTooltip.m.scss.d.ts +++ b/src/app/inventory/ItemTooltip.m.scss.d.ts @@ -1,6 +1,10 @@ // This file is automatically generated. // Please do not change this file! interface CssExports { + 'note': string; + 'noteIcon': string; + 'notes': string; + 'perkSelected': string; 'perks': string; 'stats': string; } diff --git a/src/app/inventory/ItemTooltip.tsx b/src/app/inventory/ItemTooltip.tsx index ccfa3f2c3e..d6e0432503 100644 --- a/src/app/inventory/ItemTooltip.tsx +++ b/src/app/inventory/ItemTooltip.tsx @@ -2,32 +2,43 @@ import BungieImage from 'app/dim-ui/BungieImage'; import { DimItem, DimStat } from 'app/inventory/item-types'; import { DefItemIcon } from 'app/inventory/ItemIcon'; import { useD2Definitions } from 'app/manifest/selectors'; +import { AppIcon, stickyNoteIcon } from 'app/shell/icons'; import { isKillTrackerSocket } from 'app/utils/item-utils'; import { DestinyInventoryItemDefinition } from 'bungie-api-ts/destiny2'; import clsx from 'clsx'; import _ from 'lodash'; import React from 'react'; +import { useSelector } from 'react-redux'; +import { itemNoteSelector } from './dim-item-info'; import styles from './ItemTooltip.m.scss'; export function DimItemTooltip({ item }: { item: DimItem }) { const defs = useD2Definitions()!; const itemDef = defs.InventoryItem.get(item.hash); + const savedNotes = useSelector(itemNoteSelector(item)); + if (item.bucket.sort === 'Weapons' && item.sockets) { const perkSockets = item.sockets?.allSockets.filter((s) => s.isPerk && !isKillTrackerSocket(s)); - const perks = _.takeRight(perkSockets, 2).flatMap((s) => { - const perk = s.plugged?.plugDef; - return perk ? [perk] : []; - }); - const contents = perks.length ? ( -
- {perks.map((perk, index) => ( -
- {perk.displayProperties.name} + const sockets = _.takeRight(perkSockets, 2); + + const contents = sockets.map((socket) => ( +
+ {socket.plugOptions.map((p) => ( +
1 && p === socket.plugged, + })} + data-perk-name={p.plugDef.displayProperties.name} + > + {p.plugDef.displayProperties.name}
))}
- ) : undefined; - return ; + )); + + return ; } else if (item.bucket.sort === 'Armor' && item.stats?.length) { const renderStat = (stat: DimStat) => (
@@ -41,29 +52,39 @@ export function DimItemTooltip({ item }: { item: DimItem }) { {stat.base}
); + const contents = (
{item.stats?.filter((s) => s.statHash > 0).map(renderStat)}
{item.stats?.filter((s) => s.statHash < 0).map(renderStat)}
); - return ; + + return ; } else { - return ; + return ; } } function Tooltip({ def, + notes, contents, }: { def: DestinyInventoryItemDefinition; + notes?: string; contents?: React.ReactNode; }) { return ( <>

{def.displayProperties.name}

{def.itemTypeDisplayName &&

{def.itemTypeDisplayName}

} + {notes && ( +
+ + {notes} +
+ )} {contents} ); diff --git a/src/app/inventory/StoreInventoryItem.tsx b/src/app/inventory/StoreInventoryItem.tsx index 520ecc5da9..dd2a359dbf 100644 --- a/src/app/inventory/StoreInventoryItem.tsx +++ b/src/app/inventory/StoreInventoryItem.tsx @@ -1,5 +1,7 @@ +import { compareOpenSelector } from 'app/compare/selectors'; import { useThunkDispatch } from 'app/store/thunk-dispatch'; import React from 'react'; +import { useSelector } from 'react-redux'; import ConnectedInventoryItem from './ConnectedInventoryItem'; import DraggableInventoryItem from './DraggableInventoryItem'; import { DimItem } from './item-types'; @@ -15,6 +17,7 @@ interface Props { */ export default function StoreInventoryItem({ item }: Props) { const dispatch = useThunkDispatch(); + const compareOpen = useSelector(compareOpenSelector); const doubleClicked = (e: React.MouseEvent) => { dispatch(moveItemToCurrentStore(item, e)); }; @@ -27,6 +30,7 @@ export default function StoreInventoryItem({ item }: Props) { item={item} allowFilter={true} innerRef={ref} + includeTooltip={compareOpen} onClick={onClick} onDoubleClick={doubleClicked} // for only StoreInventoryItems (the main inventory page)