Skip to content

Commit 61339e7

Browse files
committed
Merge branch 'master' into issue-171-adapter-replace
2 parents de72ee3 + 846c474 commit 61339e7

15 files changed

+85
-62
lines changed

package-dist.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ngx-ui-scroll",
3-
"version": "1.11.0-rc",
3+
"version": "1.11.0-rc.1",
44
"description": "Infinite/virtual scroll for Angular",
55
"main": "./bundles/ngx-ui-scroll.umd.js",
66
"module": "./fesm5/ngx-ui-scroll.js",

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"deploy-app": "npm run build-app && firebase deploy",
1515
"preinstall": "cd server && npm install",
1616
"postinstall": "npm run build-app",
17-
"pack:install": "npm run build && npm pack ./dist && npm install ngx-ui-scroll-1.11.0-rc.tgz --no-save",
17+
"pack:install": "npm run build && npm pack ./dist && npm install ngx-ui-scroll-1.11.0-rc.1.tgz --no-save",
1818
"pack:start": "npm run pack:install && npm start",
1919
"build": "node build.js",
2020
"publish:lib": "npm run build && npm publish ./dist",

src/component/classes/buffer.ts

+27-7
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,23 @@ export class Buffer {
1919
eofSource: Subject<boolean>;
2020
minIndexUser: number;
2121
maxIndexUser: number;
22+
startIndexUser: number;
23+
startIndex: number;
2224

23-
private startIndex: number;
2425
private pristine: boolean;
2526
private cache: Cache;
2627
readonly logger: Logger;
2728

28-
constructor(settings: Settings, startIndex: number, logger: Logger, $items?: BehaviorSubject<Item[]>) {
29+
constructor(settings: Settings, logger: Logger, $items?: BehaviorSubject<Item[]>) {
30+
this.logger = logger;
2931
this.$items = $items || new BehaviorSubject<Item[]>([]);
3032
this.bofSource = new Subject<boolean>();
3133
this.eofSource = new Subject<boolean>();
3234
this.cache = new Cache(settings.itemSize, logger);
35+
this.startIndexUser = settings.startIndex;
3336
this.minIndexUser = settings.minIndex;
3437
this.maxIndexUser = settings.maxIndex;
3538
this.reset();
36-
this.startIndex = startIndex;
37-
this.logger = logger;
3839
}
3940

4041
dispose(forever?: boolean) {
@@ -54,14 +55,32 @@ export class Buffer {
5455
this.cache.reset();
5556
this.absMinIndex = this.minIndexUser;
5657
this.absMaxIndex = this.maxIndexUser;
57-
if (typeof startIndex !== 'undefined') {
58-
this.startIndex = startIndex;
59-
}
58+
this.setCurrentStartIndex(startIndex);
6059
this._bof = false;
6160
this._eof = false;
6261
this.pristine = false;
6362
}
6463

64+
setCurrentStartIndex(newStartIndex?: any) {
65+
const min = this.minIndexUser;
66+
const max = this.maxIndexUser;
67+
const start = this.startIndexUser;
68+
let index = Number(newStartIndex);
69+
if (Number.isNaN(index)) {
70+
this.logger.log(() => `fallback startIndex to settings.startIndex (${start})`);
71+
index = start;
72+
}
73+
if (index < min) {
74+
this.logger.log(() => `setting startIndex to settings.minIndex (${min}) because ${index} < ${min}`);
75+
index = min;
76+
}
77+
if (index > max) {
78+
this.logger.log(() => `setting startIndex to settings.maxIndex (${max}) because ${index} > ${max}`);
79+
index = max;
80+
}
81+
this.startIndex = index;
82+
}
83+
6584
set items(items: Item[]) {
6685
this._items = items;
6786
this.$items.next(items);
@@ -227,6 +246,7 @@ export class Buffer {
227246
this.absMaxIndex -= toRemove.length;
228247
} else {
229248
this.absMinIndex += toRemove.length;
249+
this.startIndex += toRemove.length;
230250
}
231251
if (!virtual) {
232252
this.items = result;

src/component/classes/state.ts

+1-23
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@ export class State implements IState {
1111

1212
readonly version: string;
1313
private settings: Settings;
14-
private logger: Logger;
1514

1615
initTime: number;
17-
startIndex: number;
1816

1917
cycle: WorkflowCycleModel;
2018

@@ -28,13 +26,11 @@ export class State implements IState {
2826
return Number(new Date()) - this.initTime;
2927
}
3028

31-
constructor(version: string, settings: Settings, logger: Logger, loopCount?: number, cycleCount?: number) {
29+
constructor(version: string, settings: Settings, loopCount?: number, cycleCount?: number) {
3230
this.version = version;
3331
this.settings = settings;
34-
this.logger = logger;
3532

3633
this.initTime = Number(new Date());
37-
this.setCurrentStartIndex(settings.startIndex);
3834

3935
this.cycle = new WorkflowCycleModel(this.settings.instanceIndex, cycleCount || 1, loopCount || 0);
4036

@@ -45,22 +41,4 @@ export class State implements IState {
4541
this.scrollState = new ScrollState();
4642
}
4743

48-
setCurrentStartIndex(newStartIndex: any) {
49-
const { startIndex, minIndex, maxIndex } = this.settings;
50-
let index = Number(newStartIndex);
51-
if (Number.isNaN(index)) {
52-
this.logger.log(() => `fallback startIndex to settings.startIndex (${startIndex})`);
53-
index = startIndex;
54-
}
55-
if (index < minIndex) {
56-
this.logger.log(() => `setting startIndex to settings.minIndex (${minIndex}) because ${index} < ${minIndex}`);
57-
index = minIndex;
58-
}
59-
if (index > maxIndex) {
60-
this.logger.log(() => `setting startIndex to settings.maxIndex (${maxIndex}) because ${index} > ${maxIndex}`);
61-
index = maxIndex;
62-
}
63-
this.startIndex = index;
64-
}
65-
6644
}

src/component/classes/viewport.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ export class Viewport {
4949
}
5050
}
5151

52-
reset(scrollPosition: number) {
52+
reset(startIndex: number, scrollPosition: number) {
5353
this.setOffset();
54-
this.paddings.reset(this.getSize(), this.state.startIndex, this.offset);
54+
this.paddings.reset(this.getSize(), startIndex, this.offset);
5555
this.scrollPosition = this.paddings.backward.size || 0;
5656
this.state.scrollState.reset();
5757
}

src/component/inputs/validation.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ const onFunctionWithXAndMoreArguments = (argsCount: number) => (value: any): Val
147147

148148
const onOneOf = (tokens: string[], must: boolean) => (value: any, context: any): ValidatedValue => {
149149
const errors = [];
150-
const isSet = typeof value !== 'undefined';
150+
const isSet = value !== void 0;
151151
let noOneIsPresent = !isSet;
152152
if (!Array.isArray(tokens) || !tokens.length) {
153153
errors.push(`token list must be passed`);

src/component/interfaces/state.ts

-6
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,11 @@ export interface ScrollState {
2929

3030
export interface State {
3131
version: string;
32-
3332
initTime: number;
34-
startIndex: number;
35-
3633
cycle: WorkflowCycleModel;
37-
3834
fetch: FetchModel;
3935
clip: ClipModel;
4036
render: RenderModel;
41-
4237
scrollState: ScrollState;
43-
4438
time: number;
4539
}

src/component/processes/adapter/_base.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const getBaseAdapterProcess = (process: AdapterProcess) =>
1414

1515
static process: AdapterProcess = process;
1616

17-
static parseInput<T>(scroller: Scroller, options: T): IParseInput<T> {
17+
static parseInput<T>(scroller: Scroller, options: T, ignoreErrors = false): IParseInput<T> {
1818
const result: IParseInput<T> = {
1919
data: validate(options, ADAPTER_METHODS[process])
2020
};
@@ -27,11 +27,13 @@ export const getBaseAdapterProcess = (process: AdapterProcess) =>
2727
}), {} as T);
2828
} else {
2929
scroller.logger.log(() => result.data.showErrors());
30-
scroller.workflow.call({
31-
process,
32-
status: ProcessStatus.error,
33-
payload: { error: `Wrong argument of the "${process}" method call` }
34-
});
30+
if (!ignoreErrors) {
31+
scroller.workflow.call({
32+
process,
33+
status: ProcessStatus.error,
34+
payload: { error: `Wrong argument of the "${process}" method call` }
35+
});
36+
}
3537
}
3638

3739
return result;

src/component/processes/adapter/reload.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ export default class Reload extends getBaseAdapterProcess(AdapterProcess.reload)
88
const { viewport, state, buffer } = scroller;
99
const scrollPosition = viewport.scrollPosition;
1010

11-
state.setCurrentStartIndex(reloadIndex);
12-
buffer.reset(true, state.startIndex);
13-
viewport.reset(scrollPosition);
11+
const { params } = Reload.parseInput(scroller, { reloadIndex }, true);
12+
reloadIndex = params ? params.reloadIndex : void 0;
13+
14+
buffer.reset(true, reloadIndex);
15+
viewport.reset(buffer.startIndex, scrollPosition);
1416

1517
const payload: any = {};
1618
if (scroller.adapter.isLoading) {

src/component/processes/postFetch.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default class PostFetch extends getBaseProcess(CommonProcess.postFetch) {
5757
if (items.length < fetch.count) {
5858
if (cycle.innerLoop.isInitial) {
5959
// let's treat initial poor fetch as startIndex-bof
60-
fetchIndex = scroller.state.startIndex;
60+
fetchIndex = buffer.startIndex;
6161
} else if ((fetch.first.index as number) < buffer.minIndex) { // normal bof
6262
fetchIndex = buffer.minIndex - items.length;
6363
}

src/component/processes/preFetch.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ export default class PreFetch extends getBaseProcess(CommonProcess.preFetch) {
5050
}
5151

5252
static getStartDelta(scroller: Scroller): number { // calculate size before start index
53-
const { buffer, viewport: { offset }, state } = scroller;
53+
const { buffer, viewport: { offset } } = scroller;
5454
let startDelta = 0;
5555
if (offset) {
5656
startDelta += offset;
5757
}
5858
if (!buffer.hasItemSize) {
5959
return startDelta;
6060
}
61-
for (let index = buffer.finiteAbsMinIndex; index < state.startIndex; index++) {
61+
for (let index = buffer.finiteAbsMinIndex; index < buffer.startIndex; index++) {
6262
startDelta += buffer.getSizeByIndex(index);
6363
}
6464
scroller.logger.log(() => [
@@ -70,7 +70,7 @@ export default class PreFetch extends getBaseProcess(CommonProcess.preFetch) {
7070
static setFirstIndex(scroller: Scroller) {
7171
const { state, buffer } = scroller;
7272
const { positions: { start }, first } = state.fetch;
73-
let firstIndex = state.startIndex;
73+
let firstIndex = buffer.startIndex;
7474
let firstIndexPosition = 0;
7575
if (state.cycle.innerLoop.isInitial) {
7676
scroller.logger.log(`skipping fetch backward direction [initial loop]`);
@@ -114,12 +114,12 @@ export default class PreFetch extends getBaseProcess(CommonProcess.preFetch) {
114114
}
115115

116116
static setLastIndex(scroller: Scroller) {
117-
const { state: { fetch, startIndex, cycle }, buffer, settings } = scroller;
117+
const { state: { fetch, cycle }, buffer, settings } = scroller;
118118
const { positions: { relative, end }, first, last } = fetch;
119119
let lastIndex;
120120
if (!buffer.hasItemSize) {
121121
// just to fetch forward bufferSize items if neither averageItemSize nor itemSize are present
122-
lastIndex = startIndex + settings.bufferSize - 1;
122+
lastIndex = buffer.startIndex + settings.bufferSize - 1;
123123
scroller.logger.log(`forcing fetch forward direction [no item size]`);
124124
} else {
125125
let index = first.indexBuffer as number;

src/component/scroller.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Observable, Subscription, Observer, Subject } from 'rxjs';
1+
import { Observable, Subject } from 'rxjs';
22

33
import { Datasource } from './classes/datasource';
44
import { Settings } from './classes/settings';
@@ -52,8 +52,8 @@ export class Scroller {
5252
this.settings = new Settings(datasource.settings, datasource.devSettings, ++instanceCount);
5353
this.logger = new Logger(this, version);
5454
this.routines = new Routines(this.settings);
55-
this.state = new State(version, this.settings, this.logger, loopCount, cycleCount);
56-
this.buffer = new Buffer(this.settings, this.state.startIndex, this.logger, $items);
55+
this.state = new State(version, this.settings, loopCount, cycleCount);
56+
this.buffer = new Buffer(this.settings, this.logger, $items);
5757
this.viewport = new Viewport(element, this.settings, this.routines, this.state, this.logger);
5858
this.logger.object('uiScroll settings object', this.settings, true);
5959

@@ -83,7 +83,7 @@ export class Scroller {
8383
}
8484

8585
init(dispose$: Subject<void>, onAdapterRun$?: Observable<ProcessSubject>) {
86-
this.viewport.reset(0);
86+
this.viewport.reset(this.buffer.startIndex, 0);
8787
this.logger.stat('initialization');
8888
this.adapter.init(this.buffer, this.logger, dispose$, onAdapterRun$);
8989
}

src/ui-scroll.version.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export default '1.11.0-rc';
1+
export default '1.11.0-rc.1';

tests/adapter.reset.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ const checkReset = (config: TestBedConfig, misc: Misc, oldCheck: ICheckReset) =>
124124
const { settings, get, interruption } = config.custom;
125125
let firstIndex = oldCheck.firstVisible;
126126
let lastIndex = oldCheck.lastVisible;
127-
if (settings && typeof settings.startIndex !== 'undefined') {
127+
if (settings && settings.startIndex !== void 0) {
128128
firstIndex = settings.startIndex;
129129
lastIndex = firstIndex + (oldCheck.lastVisible - oldCheck.firstVisible);
130130
}

tests/bug.spec.ts

+27
Original file line numberDiff line numberDiff line change
@@ -217,4 +217,31 @@ describe('Bug Spec', () => {
217217
})
218218
);
219219

220+
describe('remove with increase', () =>
221+
makeTest({
222+
title: 'should shift startIndex',
223+
config: {
224+
datasourceName: 'limited-1-100-no-delay',
225+
datasourceSettings: { adapter: true, bufferSize: 5, startIndex: 1, minIndex: 1, maxIndex: 100 },
226+
},
227+
it: (misc: Misc) => async (done: Function) => {
228+
await misc.relaxNext();
229+
const { settings: { minIndex, maxIndex }, buffer, buffer: { startIndex } } = misc.scroller;
230+
const toRemove = [1, 2, 3, 4, 5];
231+
await misc.adapter.remove({
232+
predicate: ({ $index }) => toRemove.includes($index),
233+
increase: true
234+
});
235+
(misc.datasource as any).setProcessGet((result: IndexedItem[]) =>
236+
removeItems(result, toRemove, minIndex, maxIndex, true)
237+
);
238+
expect(buffer.startIndex).toBe(startIndex + toRemove.length);
239+
await misc.scrollMinMax();
240+
const maxItemsCount = Math.ceil(misc.getViewportSize() * 2 / misc.getItemSize());
241+
expect(buffer.size).toBeLessThan(maxItemsCount);
242+
done();
243+
}
244+
})
245+
);
246+
220247
});

0 commit comments

Comments
 (0)