Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions config/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -1258,6 +1258,9 @@
"Masterworked": "Masterworked",
"MaxParallelCores": "Maximum cores for parallel tasks",
"MaxParallelCoresExplanation": "Controls how many CPU cores DIM can use for intensive tasks like Loadout Optimizer and Loadout Analyzer. Higher values may improve performance but use more system resources.",
"OrnamentDisplay": "Show Ornaments on item tiles",
"OrnamentDisplayExplanationHide": "Hovering or long-pressing an item will hide its ornament",
"OrnamentDisplayExplanationShow": "Hovering or long-pressing an item will show its ornament",
"ResetToDefault": "Reset",
"ReverseSort": "Toggle forward/reverse sort",
"SetSort": "Sort items by:",
Expand Down
2 changes: 2 additions & 0 deletions src/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import './app/utils/sentry';
import { createSaveAccountsObserver } from 'app/accounts/observers';
import {
createItemSizeObserver,
createOrnamentDisplayObserver,
createThemeObserver,
createTilesPerCharColumnObserver,
setCssVariableEventListeners,
Expand Down Expand Up @@ -64,6 +65,7 @@ const i18nPromise = initi18n();
}
store.dispatch(observe(createSaveAccountsObserver()));
store.dispatch(observe(createItemSizeObserver()));
store.dispatch(observe(createOrnamentDisplayObserver()));
store.dispatch(observe(createThemeObserver()));
store.dispatch(observe(createTilesPerCharColumnObserver()));
setCssVariableEventListeners();
Expand Down
21 changes: 20 additions & 1 deletion src/app/css-variables.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { OrnamentDisplay } from '@destinyitemmanager/dim-api-types';
import { settingsSelector } from 'app/dim-api/selectors';
import { deepEqual } from 'fast-equals';
import { isPhonePortraitSelector } from './shell/selectors';
Expand All @@ -11,7 +12,7 @@ import { StoreObserver } from './store/observerMiddleware';
const KEYBOARD_THRESHOLD = 50;

function setCSSVariable(property: string, value: { toString: () => string }) {
if (value) {
if (value !== undefined && value !== null) {
document.querySelector('html')!.style.setProperty(property, value.toString());
}
}
Expand All @@ -26,6 +27,24 @@ export function createItemSizeObserver(): StoreObserver<number> {
};
}

export function createOrnamentDisplayObserver(): StoreObserver<OrnamentDisplay> {
return {
id: 'ornament-display-observer',
getObserved: (rs) => settingsSelector(rs).ornamentDisplay,
sideEffect: ({ current }) => {
setCSSVariable('--ornament-display-opacity', current === OrnamentDisplay.All ? 1 : 0);
setCSSVariable(
'--ornament-display-visibility',
current === OrnamentDisplay.All ? 'auto' : 'hidden',
);
setCSSVariable(
'--ornament-display-visibility-inverse',
current === OrnamentDisplay.All ? 'hidden' : 'auto',
);
},
};
}

export function createThemeObserver(): StoreObserver<{ theme: string; isPhonePortrait: boolean }> {
return {
id: 'theme-observer',
Expand Down
44 changes: 42 additions & 2 deletions src/app/inventory/ItemIcon.m.scss
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,55 @@ $commonBg: #366f42;
}

.animatedBackground {
display: none;
display: block;
opacity: 0;
content-visibility: hidden;

@media (prefers-reduced-motion: no-preference) {
transition:
opacity 0.2s ease-out,
content-visibility 0.2s allow-discrete;
:global(.item):hover & {
display: block;
opacity: 1;
content-visibility: auto;
}
}
}

.hasAltIcon {
display: block;
opacity: calc(1 - var(--ornament-display-opacity, 1));
content-visibility: var(--ornament-display-visibility-inverse, hidden);

@media (prefers-reduced-motion: no-preference) {
transition:
opacity 0.2s ease-out,
content-visibility 0.2s allow-discrete;
}

:global(.item):hover & {
opacity: var(--ornament-display-opacity, 1);
content-visibility: var(--ornament-display-visibility, auto);
}
}

.altIcon {
display: block;
opacity: var(--ornament-display-opacity, 1);
content-visibility: var(--ornament-display-visibility, auto);

@media (prefers-reduced-motion: no-preference) {
transition:
opacity 0.2s ease-out,
content-visibility 0.2s allow-discrete;
}

:global(.item):hover & {
opacity: calc(1 - var(--ornament-display-opacity, 1));
content-visibility: var(--ornament-display-visibility-inverse, hidden);
}
}

// This is the same size as the item image but shifted up and left by 1px to overlap the border
.shiftedLayer {
top: -1 * $item-border-width;
Expand Down
2 changes: 2 additions & 0 deletions src/app/inventory/ItemIcon.m.scss.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 13 additions & 3 deletions src/app/inventory/ItemIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,13 @@ export default function ItemIcon({ item, className }: { item: DimItem; className
: undefined;

// The actual item icon. Use the ornamented version where available.
let foreground = (item.ornamentIconDef ?? item.iconDef)?.foreground ?? item.icon;
let foreground = (item.iconDef?.foreground ?? item.icon) || '';
let altIcon = '';
if (item.ornamentIconDef) {
altIcon = item.ornamentIconDef.foreground;
}

if (!animatedBackground) {
if (!animatedBackground && !altIcon) {
backgrounds.unshift(foreground);
foreground = '';
}
Expand Down Expand Up @@ -173,10 +177,16 @@ export default function ItemIcon({ item, className }: { item: DimItem; className
{animatedBackground && (
<img src={animatedBackground} className={styles.animatedBackground} />
)}
{foreground && (
<div
style={bungieBackgroundStyle(foreground)}
className={clsx({ [styles.hasAltIcon]: Boolean(altIcon) })}
/>
)}
{altIcon && <div style={bungieBackgroundStyle(altIcon)} className={styles.altIcon} />}
{masterworkGlow && (
<div style={bungieBackgroundStyle(masterworkGlow)} className={styles.adjustOpacity} />
)}
{foreground && <div style={bungieBackgroundStyle(foreground)} />}
{seasonBanner && (
<div style={bungieBackgroundStyle(seasonBanner)} className={styles.shiftedLayer} />
)}
Expand Down
5 changes: 5 additions & 0 deletions src/app/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
// it was 16px.
--scrollbar-size: 17px;

// Whether to display ornament or base icons
--ornament-display-opacity: 1;
--ornament-display-visibility: auto;
--ornament-display-visibility-inverse: hidden;

// prevents content shift with persistent scroll-y bar
overflow-y: scroll;
}
Expand Down
31 changes: 29 additions & 2 deletions src/app/settings/SettingsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { VaultWeaponGroupingStyle } from '@destinyitemmanager/dim-api-types';
import { OrnamentDisplay, VaultWeaponGroupingStyle } from '@destinyitemmanager/dim-api-types';
import { currentAccountSelector, hasD1AccountSelector } from 'app/accounts/selectors';
import { clarityDiscordLink, clarityLink } from 'app/clarity/about';
import { settingsSelector } from 'app/dim-api/selectors';
Expand Down Expand Up @@ -81,8 +81,12 @@ export default function SettingsPage() {
(i) => i.bucket.inWeapons && !i.isExotic && i.masterwork && !i.deepsightInfo,
);
const exampleArmor = allItems.find((i) => i.bucket.inArmor && !i.isExotic);
const exampleOrnament =
allItems.find(
(i) => i !== exampleArmor && i.bucket.inArmor && i.isExotic && i.ornamentIconDef,
) || allItems.find((i) => i !== exampleArmor && i.ornamentIconDef);
const exampleArchivedArmor = allItems.find(
(i) => i !== exampleArmor && i.bucket.inArmor && !i.isExotic,
(i) => i !== exampleArmor && i !== exampleOrnament && i.bucket.inArmor && !i.isExotic,
);
const godRoll = {
wishListPerks: new Set<number>(),
Expand Down Expand Up @@ -472,6 +476,13 @@ export default function SettingsPage() {
autoLockTagged={settings.autoLockTagged}
/>
)}
{exampleOrnament && (
<InventoryItem
item={exampleOrnament}
isNew={settings.showNewItems}
autoLockTagged={settings.autoLockTagged}
/>
)}
{exampleArchivedArmor && (
<InventoryItem
item={exampleArchivedArmor}
Expand Down Expand Up @@ -504,6 +515,22 @@ export default function SettingsPage() {
</div>
)}

<div className={styles.setting}>
<Checkbox
label={t('Settings.OrnamentDisplay')}
name="ornamentDisplay"
value={settings.ornamentDisplay === OrnamentDisplay.All}
onChange={(checked, name) =>
setSetting(name, checked ? OrnamentDisplay.All : OrnamentDisplay.None)
}
/>
<div className={styles.fineprint}>
{settings.ornamentDisplay === OrnamentDisplay.All
? t('Settings.OrnamentDisplayExplanationHide')
: t('Settings.OrnamentDisplayExplanationShow')}
</div>
</div>

{$featureFlags.newItems && (
<div className={styles.setting}>
<Checkbox
Expand Down
3 changes: 3 additions & 0 deletions src/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,9 @@
"Masterworked": "Masterworked",
"MaxParallelCores": "Maximum cores for parallel tasks",
"MaxParallelCoresExplanation": "Controls how many CPU cores DIM can use for intensive tasks like Loadout Optimizer and Loadout Analyzer. Higher values may improve performance but use more system resources.",
"OrnamentDisplay": "Show Ornaments on item tiles",
"OrnamentDisplayExplanationHide": "Hovering or long-pressing an item will hide its ornament",
"OrnamentDisplayExplanationShow": "Hovering or long-pressing an item will show its ornament",
"ResetToDefault": "Reset",
"RestoreVaultSide": "Show vaulted items in their own column",
"ReverseSort": "Toggle forward/reverse sort",
Expand Down