Skip to content

Commit

Permalink
fix: last visible item & section
Browse files Browse the repository at this point in the history
  • Loading branch information
devcatalin committed Oct 27, 2021
1 parent 4bea5dc commit 1ae26e7
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 92 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, {useCallback, useMemo} from 'react';
import {ItemGroup, SectionBlueprint, SectionInstance} from '@models/navigator';
import {ItemGroupInstance, SectionBlueprint, SectionInstance} from '@models/navigator';
import {useAppSelector} from '@redux/hooks';
// import {shallowEqual} from 'react-redux';
import navSectionMap from '@src/navsections/sectionBlueprintMap';
import ItemRenderer from './ItemRenderer';
import NavSectionHeader from './SectionHeader';
Expand All @@ -22,74 +21,46 @@ function SectionRenderer<ItemType, ScopeType>(props: SectionRendererProps<ItemTy
state => state.navigator.sectionInstanceMap[sectionId]
);

const itemGroupById: Record<string, ItemGroup> = useMemo(() => {
const groupInstanceById: Record<string, ItemGroupInstance> = useMemo(() => {
return sectionInstance?.groups
.map<[string, ItemGroup]>(g => [g.id, g])
.reduce<Record<string, ItemGroup>>((acc, [k, v]) => {
.map<[string, ItemGroupInstance]>(g => [g.id, g])
.reduce<Record<string, ItemGroupInstance>>((acc, [k, v]) => {
acc[k] = v;
return acc;
}, {});
}, [sectionInstance?.groups]);

// console.log({sectionInstance});

// const sectionItemInstanceMap = useAppSelector(
// state =>
// Object.fromEntries(
// Object.values(state.navigator.itemInstanceMap)
// .filter(i => sectionInstance?.itemIds.includes(i.id))
// .map(i => [i.id, i])
// ),
// shallowEqual
// );

// const visibleItemInstances = useMemo(() => {
// return Object.values(sectionItemInstanceMap).filter(i => i.isVisible === true);
// }, [sectionItemInstanceMap]);

// const visibleGroups = useMemo(() => {
// return sectionInstance?.groups.filter(g => sectionInstance?.visibleGroupIds.includes(g.id));
// }, [sectionInstance?.groups, sectionInstance?.visibleGroupIds]);

// const isLastVisibleItemInstance = useCallback(
// (itemId: string) => {
// const lastVisibleItem = visibleItemInstances[visibleItemInstances.length - 1];
// return Boolean(lastVisibleItem && lastVisibleItem.id === itemId);
// },
// [visibleItemInstances]
// );

// const isLastVisibleItemInstanceInGroup = useCallback(
// (groupId: string, itemId: string) => {
// const isGroupVisible = sectionInstance?.visibleGroupIds.some(gid => gid === groupId);
// if (!isGroupVisible) {
// return false;
// }
// const group = sectionInstance?.groups.find(g => g.id === groupId);
// if (!group) {
// return false;
// }
// const groupVisibleItems = group.itemIds.map(id => sectionItemInstanceMap[id]).filter(i => i.isVisible);
// const lastVisibleItem = groupVisibleItems[groupVisibleItems.length - 1];
// return Boolean(lastVisibleItem && lastVisibleItem.id === itemId);
// },
// [sectionInstance?.groups, sectionItemInstanceMap, sectionInstance?.visibleGroupIds]
// );

const isGroupVisible = useCallback(
(groupId: string) => {
return sectionInstance?.visibleGroupIds.some(gid => gid === groupId);
const lastVisibleChildSectionId = useMemo(() => {
if (!sectionInstance?.visibleChildSectionIds) {
return undefined;
}
return sectionInstance.visibleChildSectionIds
? sectionInstance.visibleChildSectionIds[sectionInstance.visibleChildSectionIds.length - 1]
: undefined;
}, [sectionInstance?.visibleChildSectionIds]);

const isLastVisibleItemId = useCallback(
(itemId: string) => {
if (!sectionInstance?.visibleItemIds) {
return false;
}
const lastVisibleItemId = sectionInstance.visibleItemIds[sectionInstance.visibleItemIds.length - 1];
return itemId === lastVisibleItemId;
},
[sectionInstance?.visibleGroupIds]
[sectionInstance?.visibleItemIds]
);

// const isLastVisibleSection = useCallback(
// (subsectionName: string) => {
// const lastVisibleSection = visibleSubsections ? visibleSubsections[visibleSubsections.length - 1] : undefined;
// return Boolean(lastVisibleSection && lastVisibleSection.name === subsectionName);
// },
// [visibleSubsections]
// );
const isLastVisibleItemIdInGroup = useCallback(
(groupId: string, itemId: string) => {
const groupInstance = groupInstanceById[groupId];
if (!groupInstance) {
return false;
}
const lastVisibleItemIdInGroup = groupInstance.visibleItemIds[groupInstance.visibleItemIds.length - 1];
return itemId === lastVisibleItemIdInGroup;
},
[groupInstanceById]
);

if (!sectionInstance?.isVisible) {
return null;
Expand Down Expand Up @@ -126,49 +97,31 @@ function SectionRenderer<ItemType, ScopeType>(props: SectionRendererProps<ItemTy
itemId={itemId}
blueprint={itemBlueprint}
level={level + 1}
isLastItem={false}
isLastItem={isLastVisibleItemId(itemId)}
/>
))}
{sectionInstance?.isVisible &&
itemBlueprint &&
itemGroupById &&
groupInstanceById &&
sectionInstance.visibleGroupIds.map(groupId => {
const group = itemGroupById[groupId];
const group = groupInstanceById[groupId];
return (
<React.Fragment key={group.id}>
<S.NameContainer style={{color: 'red'}}>
<S.Name level={level + 1}>{group.name}</S.Name>
</S.NameContainer>
{group.itemIds.map(itemId => (
{group.visibleItemIds.map(itemId => (
<ItemRenderer<ItemType, ScopeType>
key={itemId}
itemId={itemId}
blueprint={itemBlueprint}
level={level + 2}
isLastItem={false} // isLastVisibleItemInstanceInGroup(group.name, itemInstance.id)
isLastItem={isLastVisibleItemIdInGroup(group.id, itemId)}
/>
))}
</React.Fragment>
);
})}
{/* {sectionInstance?.isVisible && // !isCollapsed &&
itemBlueprint &&
sectionInstance.visibleGroupIds.map(groupId => (
<React.Fragment key={group.id}>
<S.NameContainer style={{color: 'red'}}>
<S.Name level={level + 1}>{group.name}</S.Name>
</S.NameContainer>
{group.itemIds.map(itemId => (
<ItemRenderer<ItemType, ScopeType>
key={itemId}
itemId={itemId}
blueprint={itemBlueprint}
level={level + 2}
isLastItem={false} // isLastVisibleItemInstanceInGroup(group.name, itemInstance.id)
/>
))}
</React.Fragment>
))} */}
{sectionBlueprint.childSectionIds &&
sectionBlueprint.childSectionIds
.map(childSectionId => navSectionMap.getById(childSectionId))
Expand All @@ -177,7 +130,7 @@ function SectionRenderer<ItemType, ScopeType>(props: SectionRendererProps<ItemTy
key={child.name}
sectionBlueprint={child}
level={level + 1}
isLastSection={false} // isLastVisibleSection(child.name)
isLastSection={child.id === lastVisibleChildSectionId}
/>
))}
</>
Expand Down
11 changes: 8 additions & 3 deletions src/models/navigator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export interface ItemBlueprint<RawItemType, ScopeType> {
customization?: ItemCustomization;
}

export interface ItemGroup {
export interface ItemGroupBlueprint {
id: string;
name: string;
itemIds: string[];
Expand All @@ -62,14 +62,18 @@ export interface SectionBlueprint<RawItemType, ScopeType = any> {
childSectionIds?: string[];
builder?: {
getRawItems?: (scope: ScopeType) => RawItemType[];
getGroups?: (scope: ScopeType) => ItemGroup[];
getGroups?: (scope: ScopeType) => ItemGroupBlueprint[];
isLoading?: (scope: ScopeType, items: RawItemType[]) => boolean;
isVisible?: (scope: ScopeType, items: RawItemType[]) => boolean;
isInitialized?: (scope: ScopeType, items: RawItemType[]) => boolean;
};
itemBlueprint?: ItemBlueprint<RawItemType, ScopeType>;
}

export interface ItemGroupInstance extends ItemGroupBlueprint {
visibleItemIds: string[];
}

export interface ItemInstance {
id: string;
name: string;
Expand All @@ -84,9 +88,10 @@ export interface ItemInstance {
export interface SectionInstance {
id: string;
itemIds: string[];
groups: ItemGroup[];
groups: ItemGroupInstance[];
visibleItemIds: string[];
visibleGroupIds: string[];
visibleChildSectionIds?: string[];
isLoading: boolean;
isVisible: boolean;
isInitialized: boolean;
Expand Down
17 changes: 13 additions & 4 deletions src/navsections/sectionBlueprintMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ const computeSectionVisibility = (
const childSectionInstance = sectionInstanceMap[childSectionId];
const isChildSectionVisible = computeSectionVisibility(childSectionInstance, sectionInstanceMap);
childSectionVisibilityMap[childSectionId] = isChildSectionVisible;
if (isChildSectionVisible) {
if (sectionInstance.visibleChildSectionIds) {
sectionInstance.visibleChildSectionIds.push(childSectionId);
} else {
sectionInstance.visibleChildSectionIds = [childSectionId];
}
}
});
sectionInstance.isVisible =
sectionInstance.isVisible || Object.values(childSectionVisibilityMap).some(isVisible => isVisible === true);
Expand Down Expand Up @@ -123,14 +130,16 @@ const processSectionBlueprints = (state: RootState, dispatch: AppDispatch) => {
sectionBuilder?.isInitialized ? sectionBuilder.isInitialized(sectionScope, rawItems) : true
);
const sectionGroups = sectionBuilder?.getGroups ? sectionBuilder.getGroups(sectionScope) : [];
const sectionInstanceGroups = sectionGroups.map(g => ({
...g,
visibleItemIds: g.itemIds.filter(itemId => itemInstanceMap[itemId].isVisible === true),
}));
const visibleItemIds = itemInstances?.filter(i => i.isVisible === true).map(i => i.id) || [];
const visibleGroupIds = sectionGroups
.filter(g => g.itemIds.some(itemId => itemInstanceMap[itemId].isVisible === true))
.map(g => g.id);
const visibleGroupIds = sectionInstanceGroups.filter(g => g.visibleItemIds.length > 0).map(g => g.id);
const navSectionInstance: SectionInstance = {
id: sectionBlueprint.id,
itemIds: itemInstances?.map(i => i.id) || [],
groups: sectionGroups,
groups: sectionInstanceGroups,
isLoading: Boolean(sectionBuilder?.isLoading ? sectionBuilder.isLoading(sectionScope, rawItems) : false),
isVisible:
Boolean(sectionBuilder?.isVisible && sectionBuilder.isVisible(sectionScope, rawItems)) ||
Expand Down

0 comments on commit 1ae26e7

Please sign in to comment.