Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add useDetachedRecycle option, fix loading state, offset #585

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
"lerna": "^4.0.0",
"typescript": "^4.5.0 <4.6.0"
},
"resolutions": {
"@types/lodash": "4.14.30",
"@storybook/addon-essentials": "6.1.11"
},
"workspaces": {
"packages": [
"packages/*",
Expand Down
4 changes: 2 additions & 2 deletions packages/infinitegrid/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@egjs/infinitegrid",
"version": "4.12.0",
"version": "4.13.0-beta.8",
"description": "A module used to arrange elements including content infinitely according to grid type. With this module, you can implement various grids composed of different card elements whose sizes vary. It guarantees performance by maintaining the number of DOMs the module is handling under any circumstance",
"module": "dist/infinitegrid.esm.js",
"main": "dist/infinitegrid.cjs.js",
Expand Down Expand Up @@ -122,7 +122,7 @@
"@cfcs/core": "^0.0.5",
"@egjs/children-differ": "^1.0.1",
"@egjs/component": "^3.0.0",
"@egjs/grid": "~1.16.0",
"@egjs/grid": "1.17.0-beta.3",
"@egjs/list-differ": "^1.0.0"
}
}
2 changes: 1 addition & 1 deletion packages/infinitegrid/src/GroupManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export class GroupManager extends Grid<GroupManagerOptions> {
}

public waitEndLoading() {
if (this._loadingGrid.type) {
if (!this._loadingGrid.isWaitEnd && this._loadingGrid.type) {
this._loadingGrid.isWaitEnd = true;
return true;
}
Expand Down
71 changes: 68 additions & 3 deletions packages/infinitegrid/src/Infinite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export interface InfiniteOptions {
useRecycle?: boolean;
threshold?: number;
defaultDirection?: "start" | "end";
isReachStart?: boolean;
isReachEnd?: boolean;
}

export interface InfiniteItemPart {
Expand Down Expand Up @@ -62,9 +64,17 @@ export class Infinite extends Component<InfiniteEvents> {
threshold: 0,
useRecycle: true,
defaultDirection: "end",
isReachStart: false,
isReachEnd: false,
...options,
};
}
public set isReachStart(value: boolean) {
this.options.isReachStart = value;
}
public set isReachEnd(value: boolean) {
this.options.isReachEnd = value;
}
public scroll(scrollPos: number) {
const prevStartCursor = this.startCursor;
const prevEndCursor = this.endCursor;
Expand All @@ -75,11 +85,34 @@ export class Infinite extends Component<InfiniteEvents> {
defaultDirection,
threshold,
useRecycle,
isReachEnd,
isReachStart,
} = this.options;
const isDirectionEnd = defaultDirection === "end";

if (!length) {
this.trigger(isDirectionEnd ? "requestAppend" : "requestPrepend", {
if (isReachStart && isReachEnd) {
return;
}
let requestType: "requestAppend" | "requestPrepend" | "" = "";

if (!isReachEnd && isDirectionEnd) {
// 1st order
requestType = "requestAppend";
} else if (!isReachStart && !isDirectionEnd) {
// 2nd order
requestType = "requestPrepend";
} else if (!isReachEnd && isReachStart) {
// 3rd order
requestType = "requestAppend";
} else if (isReachEnd && !isReachStart) {
// 4th order
requestType = "requestPrepend";
}
if (!requestType) {
return;
}
this.trigger(requestType, {
key: undefined,
isVirtual: false,
});
Expand Down Expand Up @@ -211,12 +244,12 @@ export class Infinite extends Component<InfiniteEvents> {
}
}
} else if (!this._requestVirtualItems()) {
if ((!isDirectionEnd || !isEnd) && isStart) {
if ((!isDirectionEnd || !isEnd || isReachEnd) && isStart && !isReachStart) {
this.trigger("requestPrepend", {
key: items[prevStartCursor].key,
isVirtual: false,
});
} else if ((isDirectionEnd || !isStart) && isEnd) {
} else if ((isDirectionEnd || !isStart || isReachStart) && isEnd && !isReachEnd) {
this.trigger("requestAppend", {
key: items[prevEndCursor].key,
isVirtual: false,
Expand Down Expand Up @@ -361,6 +394,38 @@ export class Infinite extends Component<InfiniteEvents> {
|| visibleResult.removed.length > 0
|| visibleResult.changed.length > 0;
}

const defaultDirection = this.options.defaultDirection;
let prevOutline: number[] = [];
const outlinedItems = [...nextItems];

if (defaultDirection === "start") {
outlinedItems.reverse();
}
outlinedItems.forEach((item, i) => {
if (i > 0 && prevOutline.length) {
if (defaultDirection === "start") {
if (!item.endOutline.length) {
item.endOutline = [...prevOutline];
}
if (!item.startOutline.length) {
item.startOutline = [...item.endOutline];
}
} else {
if (!item.startOutline.length) {
item.startOutline = [...prevOutline];
}
if (!item.endOutline.length) {
item.endOutline = [...item.startOutline];
}
}
}
if (defaultDirection === "start") {
prevOutline = item.startOutline;
} else {
prevOutline = item.endOutline;
}
});
this.setItems(nextItems);
this.setCursors(nextStartCursor, nextEndCursor);
return isChange;
Expand Down
65 changes: 59 additions & 6 deletions packages/infinitegrid/src/InfiniteGrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Grid, {
GridItem,
ResizeWatcherResizeEvent,
getUpdatedItems,
PROPERTY_TYPE,
} from "@egjs/grid";
import {
DIRECTION,
Expand Down Expand Up @@ -93,9 +94,16 @@ class InfiniteGrid<Options extends InfiniteGridOptions = InfiniteGridOptions> ex
renderer: null,
threshold: 100,
useRecycle: true,
useDetachedRecycle: false,
scrollContainer: null,
isReachStart: false,
isReachEnd: false,
appliedItemChecker: (() => false) as (item: InfiniteGridItem, grid: Grid) => boolean,
} as Required<InfiniteGridOptions>;
public static infinitegridTypes = {
isReachEnd: PROPERTY_TYPE.PROPERTY,
isReachStart: PROPERTY_TYPE.PROPERTY,
};
public static propertyTypes = INFINITEGRID_PROPERTY_TYPES;
protected wrapperElement: HTMLElement;
protected scrollManager: ScrollManager;
Expand Down Expand Up @@ -394,7 +402,6 @@ class InfiniteGrid<Options extends InfiniteGridOptions = InfiniteGridOptions> ex
scrollManager: this.scrollManager.getStatus(),
};
}

/**
* You can set placeholders to restore status or wait for items to be added.
* @ko status 복구 또는 아이템 추가 대기를 위한 placeholder를 설정할 수 있다.
Expand Down Expand Up @@ -622,6 +629,16 @@ class InfiniteGrid<Options extends InfiniteGridOptions = InfiniteGridOptions> ex
public isWait() {
return !!this._waitType;
}
/**
* <ko>scrollOffset(startOffset) 또는 scrollSize의 사이즈를 수동으로 업데이트 한다. 변경이 됐다면 스크롤이 발생시킨다.</ko>
*/
public resizeScroll() {
const result = this._resizeScroll();

if (result) {
this._scroll();
}
}
/**
* Releases the instnace and events and returns the CSS of the container and elements.
* @ko 인스턴스와 이벤트를 해제하고 컨테이너와 엘리먼트들의 CSS를 되돌린다.
Expand All @@ -647,6 +664,14 @@ class InfiniteGrid<Options extends InfiniteGridOptions = InfiniteGridOptions> ex
};
});
}
private _setIsReachStart(value: boolean) {
this.options.isReachStart = value;
this.infinite.isReachStart = value;
}
private _setIsReachEnd(value: boolean) {
this.options.isReachEnd = value;
this.infinite.isReachEnd = value;
}
private _syncItems(state?: Record<string, any>): void {
this._getRenderer().syncItems(this._getRendererItems(), state);
}
Expand All @@ -659,9 +684,10 @@ class InfiniteGrid<Options extends InfiniteGridOptions = InfiniteGridOptions> ex
private _resizeScroll() {
const scrollManager = this.scrollManager;

scrollManager.resize();

const result = scrollManager.resize();
this.infinite.setSize(scrollManager.getContentSize());

return result;
}
private _syncGroups(isUpdate?: boolean) {
const infinite = this.infinite;
Expand All @@ -672,6 +698,7 @@ class InfiniteGrid<Options extends InfiniteGridOptions = InfiniteGridOptions> ex
}
this._syncInfinite();
this.groupManager.setCursors(infinite.getStartCursor(), infinite.getEndCursor());

if (isUpdate) {
this._update();
} else {
Expand Down Expand Up @@ -746,6 +773,10 @@ class InfiniteGrid<Options extends InfiniteGridOptions = InfiniteGridOptions> ex

if (orgItem.mountState !== MOUNT_STATE.UNCHECKED) {
orgItem.mountState = MOUNT_STATE.UNMOUNTED;

if (this.options.useDetachedRecycle) {
orgItem.element = null;
}
}
});

Expand Down Expand Up @@ -846,6 +877,14 @@ class InfiniteGrid<Options extends InfiniteGridOptions = InfiniteGridOptions> ex
nextGroupKey: e.nextKey,
nextGroupKeys: e.nextKeys || [],
isVirtual: e.isVirtual,
reachStart: () => {
this._setIsReachStart(true);
this._scroll();
},
reachEnd: () => {
this._setIsReachEnd(true);
this._scroll();
},
wait: () => {
this.wait(direction);
},
Expand Down Expand Up @@ -877,6 +916,7 @@ class InfiniteGrid<Options extends InfiniteGridOptions = InfiniteGridOptions> ex
const infinite = this.infinite;
const scrollManager = this.scrollManager;
const scrollPos = scrollManager.getRelativeScrollPos()!;
const orgScrollPos = scrollManager.getScrollPos()!;
const prevScrollSize = infinite.getScrollSize();
const prevContainerSize = infinite.getSize();
const prevVisibleArea = infinite.getVisibleArea(scrollPos, direction);
Expand Down Expand Up @@ -918,16 +958,23 @@ class InfiniteGrid<Options extends InfiniteGridOptions = InfiniteGridOptions> ex
let offset = nextPos - prevPos;

// If reversed, scroll size (case where container size is reduced)
const nextScrollSize = infinite.getScrollSize();
const nextContainerSize = infinite.getSize();

if (offset < 0) {
const nextScrollSize = infinite.getScrollSize();
const nextContainerSize = infinite.getSize();
const endOffset = Math.max(scrollPos - Math.max(0, prevScrollSize - prevContainerSize), 0);
const nextScollPos
= Math.min(scrollPos, Math.max(0, nextScrollSize - nextContainerSize))
+ endOffset;

// The scroll size is restored to the extent that it has been reduced.
offset += scrollPos - nextScollPos;
} else if (offset > 0) {
// If it is smaller than the scroll size when in the forward direction, the offset is 0.
const maxScrollPos = Math.max(0, nextScrollSize - nextContainerSize);
const nextScrollPos = orgScrollPos + offset;

offset = Math.max(0, Math.min(maxScrollPos, nextScrollPos) - orgScrollPos);
}

this.scrollManager.scrollBy(offset);
Expand Down Expand Up @@ -1019,6 +1066,12 @@ class InfiniteGrid<Options extends InfiniteGridOptions = InfiniteGridOptions> ex
}
}

interface InfiniteGrid extends Properties<typeof InfiniteGrid> { }
interface InfiniteGrid extends Properties<typeof InfiniteGrid> {
isReachStart: boolean;
isReachEnd: boolean;
}

export default InfiniteGrid;



8 changes: 8 additions & 0 deletions packages/infinitegrid/src/ScrollManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ export class ScrollManager extends Component<ScrollManagerEvents> {
eventTarget.scrollTop += y;
}
}
/**
* @return Returns true if scrollOffset or contentSize has changed, otherwise returns false. <ko>scrollOffset 또는 contentSize가 변화가 있으면 true 아니면 false를 반환한다.</ko>
*/
public resize() {
const scrollContainer = this.scrollContainer;
const horizontal = this.options.horizontal;
Expand All @@ -139,6 +142,9 @@ export class ScrollManager extends Component<ScrollManagerEvents> {
: scrollContainer.getBoundingClientRect();
const containerRect = this.container.getBoundingClientRect();

const prevScrollOffset = this.scrollOffset;
const prevContentSize = this.contentSize;

this.scrollOffset = (this.getOrgScrollPos()! || 0) + (horizontal
? containerRect.left - scrollContainerRect.left
: containerRect.top - scrollContainerRect.top);
Expand All @@ -148,6 +154,8 @@ export class ScrollManager extends Component<ScrollManagerEvents> {
} else {
this.contentSize = horizontal ? scrollContainer.offsetWidth : scrollContainer.offsetHeight;
}

return prevScrollOffset !== this.scrollOffset || prevContentSize !== this.contentSize;
}
public destroy() {
const container = this.container;
Expand Down
2 changes: 1 addition & 1 deletion packages/infinitegrid/src/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export const IGNORE_PROPERITES_MAP = {
autoResize: true,
} as const;


export const INFINITEGRID_PROPERTY_TYPES = {
...GRID_PROPERTY_TYPES,
};
Expand Down Expand Up @@ -43,6 +42,7 @@ export const ITEM_INFO_PROPERTIES: Record<keyof InfiniteGridItemInfo, true> = {


export const INFINITEGRID_METHODS = [
"resizeScroll",
"insertByGroupIndex",
"updateItems",
"getItems",
Expand Down
Loading
Loading