Skip to content

Commit

Permalink
Merge pull request #10172 from DestinyItemManager/lo-sections
Browse files Browse the repository at this point in the history
More changes to bring LO in line with Loadout Editor
  • Loading branch information
bhollis authored Dec 18, 2023
2 parents f1bc999 + dffcd28 commit 72bf5b1
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 45 deletions.
5 changes: 3 additions & 2 deletions config/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -586,17 +586,17 @@
"ChooseAlternateTitle": "Choose another item",
"CompareLoadout": "Compare Loadout",
"ConfirmOverwrite": "Are you sure you want to replace the armor in the loadout \"{{name}}\" with this new set of armor?",
"CreateLoadout": "Save Loadout",
"DisabledDueToMaintenance": "The Loadout Optimizer is currently disabled due to Bungie API maintenance.",
"EquipItems": "Equip",
"ExcludeItem": "Exclude Item",
"ExcludedItems": "Excluded Items",
"Exotic": "Exotic Armor",
"ExistingLoadout": "Existing Loadout",
"ExoticSpecialCategory": "Special",
"Filter": "Filters",
"Legendary": "Legendary",
"LockEquipped": "Pin equipped",
"LockItem": "Pin item",
"PinnedItems": "Pinned Items",
"MissingClass": "Build is for: {{className}}",
"MissingClassDescription": "The build you're trying to view is for a character class you don't have.",
"NoBuildsFoundExplainer": {
Expand Down Expand Up @@ -764,6 +764,7 @@
"RestoreAllItems": "All Items",
"Save": "Save",
"SaveLoadout": "Save Loadout",
"UpdateLoadout": "Update Loadout",
"SaveAsDIM": "Save as DIM Loadout",
"SaveAsNew": "Save as New",
"SaveAsNewTooltip": "Keep the original loadout and save this as a new loadout",
Expand Down
3 changes: 2 additions & 1 deletion src/app/loadout-builder/LoadoutBucketDropTarget.m.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.canDrop {
outline: 1px solid #666;
outline: 1px solid white;
outline-offset: 4px;
&.over {
outline: 1px solid var(--theme-accent-primary);
}
Expand Down
2 changes: 2 additions & 0 deletions src/app/loadout-builder/LoadoutBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -361,12 +361,14 @@ export default memo(function LoadoutBuilder({
pinnedItems={pinnedItems}
searchFilter={searchFilter}
lbDispatch={lbDispatch}
className={styles.subclassSection}
/>
<LoadoutOptimizerExcludedItems
chooseItem={chooseItem}
excludedItems={excludedItems}
searchFilter={searchFilter}
lbDispatch={lbDispatch}
className={styles.subclassSection}
/>
{isPhonePortrait && (
<div className={styles.guide}>
Expand Down
10 changes: 0 additions & 10 deletions src/app/loadout-builder/filter/LoadoutOptimizerMenuItems.m.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,3 @@
composes: flexColumn from '../../dim-ui/common.m.scss';
gap: 4px;
}

.buttons {
display: flex;
flex-direction: row;
> * {
flex: 1;
}

gap: 4px;
}

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

54 changes: 32 additions & 22 deletions src/app/loadout-builder/filter/LoadoutOptimizerMenuItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { t } from 'app/i18next-t';
import { DimItem } from 'app/inventory/item-types';
import { DimStore } from 'app/inventory/store-types';
import { isLoadoutBuilderItem } from 'app/loadout/item-utils';
import { AddItemButton } from 'app/loadout/loadout-edit/LoadoutEditBucket';
import LoadoutEditSection from 'app/loadout/loadout-edit/LoadoutEditSection';
import { ItemFilter } from 'app/search/filter-types';
import { AppIcon, faTimesCircle, pinIcon } from 'app/shell/icons';
import { objectValues } from 'app/utils/util-types';
import _ from 'lodash';
import React, { Dispatch, memo, useCallback } from 'react';
Expand All @@ -24,12 +25,14 @@ export const LoadoutOptimizerPinnedItems = memo(function LoadoutOptimizerPinnedI
pinnedItems,
searchFilter,
lbDispatch,
className,
}: {
chooseItem: ChooseItemFunction;
selectedStore: DimStore;
pinnedItems: PinnedItems;
searchFilter: ItemFilter;
lbDispatch: Dispatch<LoadoutBuilderAction>;
className?: string;
}) {
/**
* Lock currently equipped items on a character
Expand All @@ -46,6 +49,11 @@ export const LoadoutOptimizerPinnedItems = memo(function LoadoutOptimizerPinnedI
[lbDispatch],
);
const unpinItem = (item: DimItem) => lbDispatch({ type: 'unpinItem', item });
const clear = () =>
lbDispatch({
type: 'setPinnedItems',
items: [],
});

const chooseLockItem = chooseItem(
pinItem,
Expand All @@ -58,23 +66,21 @@ export const LoadoutOptimizerPinnedItems = memo(function LoadoutOptimizerPinnedI
);

return (
<LoadoutBucketDropTarget className={styles.area} onItemLocked={pinItem}>
{Boolean(allPinnedItems.length) && (
<LoadoutEditSection
className={className}
title={t('LoadoutBuilder.PinnedItems')}
onClear={clear}
onSyncFromEquipped={lockEquipped}
>
<LoadoutBucketDropTarget className={styles.area} onItemLocked={pinItem}>
<div className={styles.itemGrid}>
{allPinnedItems.map((lockedItem) => (
<LockedItem key={lockedItem.id} lockedItem={lockedItem} onRemove={unpinItem} />
))}
<AddItemButton onClick={chooseLockItem} title={t('LoadoutBuilder.LockItem')} />
</div>
)}
<div className={styles.buttons}>
<button type="button" className="dim-button" onClick={chooseLockItem}>
<AppIcon icon={pinIcon} /> {t('LoadoutBuilder.LockItem')}
</button>
<button type="button" className="dim-button" onClick={lockEquipped}>
<AppIcon icon={pinIcon} /> {t('LoadoutBuilder.LockEquipped')}
</button>
</div>
</LoadoutBucketDropTarget>
</LoadoutBucketDropTarget>
</LoadoutEditSection>
);
});

Expand All @@ -83,11 +89,13 @@ export const LoadoutOptimizerExcludedItems = memo(function LoadoutOptimizerExclu
excludedItems,
searchFilter,
lbDispatch,
className,
}: {
chooseItem: ChooseItemFunction;
excludedItems: ExcludedItems;
searchFilter: ItemFilter;
lbDispatch: Dispatch<LoadoutBuilderAction>;
className?: string;
}) {
const excludeItem = useCallback(
(item: DimItem) => lbDispatch({ type: 'excludeItem', item }),
Expand All @@ -100,21 +108,23 @@ export const LoadoutOptimizerExcludedItems = memo(function LoadoutOptimizerExclu
const allExcludedItems = _.sortBy(_.compact(objectValues(excludedItems)).flat(), (i) =>
LockableBucketHashes.indexOf(i.bucket.hash),
);

const clear = () => lbDispatch({ type: 'clearExcludedItems' });
return (
<LoadoutBucketDropTarget className={styles.area} onItemLocked={excludeItem}>
{Boolean(allExcludedItems.length) && (
<LoadoutEditSection
className={className}
title={t('LoadoutBuilder.ExcludedItems')}
onClear={clear}
>
<LoadoutBucketDropTarget className={styles.area} onItemLocked={excludeItem}>
<div className={styles.itemGrid}>
{allExcludedItems.map((lockedItem) => (
<LockedItem key={lockedItem.id} lockedItem={lockedItem} onRemove={unExcludeItem} />
))}
<AddItemButton onClick={chooseExcludeItem} title={t('LoadoutBuilder.ExcludeItem')} />
</div>
)}
<div className={styles.buttons}>
<button type="button" className="dim-button" onClick={chooseExcludeItem}>
<AppIcon icon={faTimesCircle} /> {t('LoadoutBuilder.ExcludeItem')}
</button>
</div>
</LoadoutBucketDropTarget>
</LoadoutBucketDropTarget>
</LoadoutEditSection>
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export default function GeneratedSetButtons({
return (
<div className={styles.buttons}>
<button type="button" className="dim-button" onClick={openLoadout}>
{t('LoadoutBuilder.CreateLoadout')}
{isEditingExistingLoadout ? t('Loadouts.UpdateLoadout') : t('Loadouts.SaveLoadout')}
</button>
{canCompareLoadouts && (
<button
Expand Down
6 changes: 6 additions & 0 deletions src/app/loadout-builder/loadout-builder-reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ type LoadoutBuilderConfigAction =
| { type: 'unpinItem'; item: DimItem }
| { type: 'excludeItem'; item: DimItem }
| { type: 'unexcludeItem'; item: DimItem }
| { type: 'clearExcludedItems' }
| { type: 'autoStatModsChanged'; autoStatMods: boolean }
| { type: 'lockedModsChanged'; lockedMods: number[] }
| { type: 'removeLockedMod'; mod: ResolvedLoadoutMod }
Expand Down Expand Up @@ -465,6 +466,11 @@ function lbConfigReducer(defs: D2ManifestDefinitions) {
},
};
}
case 'clearExcludedItems':
return {
...state,
excludedItems: {},
};
case 'lockedModsChanged':
return updateLoadout(state, updateMods(action.lockedMods));
case 'assumeArmorMasterworkChanged': {
Expand Down
22 changes: 16 additions & 6 deletions src/app/loadout/loadout-edit/LoadoutEditBucket.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,11 @@ function ItemBucket({
const showAddUnequipped = equipped.length > 0 && unequipped.length < maxSlots - 1;

const addUnequipped = showAddUnequipped && (
<button
type="button"
<AddItemButton
key="addbutton"
className={styles.addButton}
onClick={() => handlePlaceholderClick(false)}
title={t('Loadouts.AddUnequippedItems')}
>
<AppIcon icon={addIcon} />
</button>
/>
);

const renderItem = (li: ResolvedLoadoutItem) => (
Expand Down Expand Up @@ -297,6 +293,20 @@ function DraggableItem({
);
}

export function AddItemButton({
onClick,
title,
}: {
onClick: React.MouseEventHandler;
title: string;
}) {
return (
<button type="button" className={styles.addButton} onClick={onClick} title={title}>
<AppIcon icon={addIcon} />
</button>
);
}

function FashionButton({
loadout,
items,
Expand Down
5 changes: 3 additions & 2 deletions src/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -631,20 +631,19 @@
"ChooseAlternateTitle": "Choose another item",
"CompareLoadout": "Compare Loadout",
"ConfirmOverwrite": "Are you sure you want to replace the armor in the loadout \"{{name}}\" with this new set of armor?",
"CreateLoadout": "Save Loadout",
"DecreaseStatPriority": "Decrease stat priority",
"DisabledByAutoStatMods": "Stat mods are being chosen automatically by Loadout Optimizer.",
"DisabledDueToMaintenance": "The Loadout Optimizer is currently disabled due to Bungie API maintenance.",
"EquipItems": "Equip",
"ExcludeItem": "Exclude Item",
"ExcludedItems": "Excluded Items",
"ExistingLoadout": "Existing Loadout",
"Exotic": "Exotic Armor",
"ExoticSpecialCategory": "Special",
"Filter": "Filters",
"IgnoreStat": "If unchecked, Loadout Optimizer will pretend this stat doesn't exist when building sets",
"IncreaseStatPriority": "Increase stat priority",
"Legendary": "Legendary",
"LockEquipped": "Pin equipped",
"LockItem": "Pin item",
"MissingClass": "Build is for: {{className}}",
"MissingClassDescription": "The build you're trying to view is for a character class you don't have.",
Expand Down Expand Up @@ -677,6 +676,7 @@
"OptimizerExplanationSearch": "Use the search bar to narrow down which armor to consider. If no armor matches the search in a slot, all armor in that slot will be considered.",
"OptimizerExplanationStats": "Drag the most important stats to the top, and disable stats you don't want to optimize for.",
"OptimizerSet": "Optimizer Set",
"PinnedItems": "Pinned Items",
"ProcessingSets": "Finding highest tier sets...",
"SaveAs": "Save as",
"SpeedReport": "Generated {{combos, number}} combinations in {{time}} seconds",
Expand Down Expand Up @@ -857,6 +857,7 @@
"UnassignedModError": "Mod didn't fit on your current armor",
"Undo": "Undo",
"Update": "Save Changes",
"UpdateLoadout": "Update Loadout",
"VendorsCannotEquip": "You don't have these items. Tap to pick a replacement or click the X to remove:"
},
"Manifest": {
Expand Down

0 comments on commit 72bf5b1

Please sign in to comment.