Skip to content

Commit

Permalink
deglitchFalse
Browse files Browse the repository at this point in the history
  • Loading branch information
gerardcarbo committed Mar 6, 2019
1 parent 5b673b3 commit faae8be
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 35 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "virtual-repeat-angular-lib-app",
"version": "0.4.4",
"version": "0.4.5",
"scripts": {
"serve": "ng serve",
"build_prod": "ng build --prod",
Expand All @@ -11,7 +11,7 @@
"build_lib": "ng build --prod virtual-repeat-angular-lib",
"npm_pack": "cp README.md dist/virtual-repeat-angular-lib && cd dist/virtual-repeat-angular-lib && npm pack && cp *.tgz ../releases/",
"npm_build_and_package": "npm run build_lib && npm run npm_pack",
"npm_publish": "npm publish dist/virtual-repeat-angular-lib/virtual-repeat-angular-0.4.4.tgz",
"npm_publish": "npm publish dist/virtual-repeat-angular-lib/virtual-repeat-angular-0.4.5.tgz",
"ngh_publish": "npm run build_lib && ng build --prod --base-href https://gerardcarbo.github.io/virtual-repeat-angular/ && ngh --dir dist/virtual-repeat-angular-lib-app",
"git_push": "git push -u origin master",
"git_push_force": "git push -u -f origin master",
Expand Down
2 changes: 1 addition & 1 deletion projects/virtual-repeat-angular-lib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "virtual-repeat-angular",
"version": "0.4.4",
"version": "0.4.5",
"author": {
"name": "Gerard Carbó"
},
Expand Down
52 changes: 27 additions & 25 deletions projects/virtual-repeat-angular-lib/src/lib/logger.service.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
import { isDevMode } from '@angular/core';
import { noop } from 'rxjs';

export class LoggerService {
log: any;
constructor() {
const forceLog = Boolean(localStorage.getItem('gcvra_force_log')); // force log even in devMode
const filterLog = localStorage.getItem('gcvra_filter_log'); // filter log lines (; separated list)
const bLog = Boolean(localStorage.getItem('gcvra_log')); // enable log
const filterLog = localStorage.getItem('gcvra_log_filter'); // filter log lines (; separated list)
let filterLogTerms: string[];
if (filterLog) {
filterLogTerms = filterLog.split(';').map(term => term.trim().toLowerCase()).filter(term => !!term);
filterLogTerms = filterLog
.split(';')
.map(term => term.trim().toLowerCase())
.filter(term => !!term);
}
setTimeout(() => { // hack to be able to use isDevMode()
if (isDevMode() || forceLog) {
if (filterLog) {
this.log = function (text: string, ...args: any[]) {
let done = false;
filterLogTerms.forEach(term => {
if (!done && text.toLowerCase().indexOf(term) !== -1) {
console.log(text, ...args);
done = true;
}
});
return;
};
} else {
this.log = function (text: string, ...args: any[]) {
console.log(text, ...args);
};
}
if (bLog) {
if (filterLog) {
this.log = function(text: string, ...args: any[]) {
let done = false;
filterLogTerms.forEach(term => {
if (!done && text.toLowerCase().indexOf(term) !== -1) {
console.log(text, ...args);
done = true;
}
});
return;
};
} else {
this.log = function(text: string, ...args: any[]) {
console.log(text, ...args);
};
}
}, 100);
} else {
this.log = noop;
}
}

log(text: string, ...args: any[]) { }
}
181 changes: 178 additions & 3 deletions projects/virtual-repeat-angular-lib/src/lib/rxjs.operators.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import { TestBed, inject } from '@angular/core/testing';

import { LoggerService } from './logger.service';
import { Subject } from 'rxjs';
import { deglitch, throttleTimeUntilChanged } from './rxjs.operators';
import {
deglitch,
throttleTimeUntilChanged,
deglitchFalse
} from './rxjs.operators';
import { tap } from 'rxjs/operators';

describe('RXJs operators', () => {

beforeEach(() => {
TestBed.configureTestingModule({
providers: [LoggerService]
Expand Down Expand Up @@ -111,7 +114,7 @@ describe('RXJs operators', () => {
});

describe('deglitch', () => {
it('should change simple', function(done) {
it('should change simple (0-->1)', function(done) {
inject([LoggerService], function(logger: LoggerService) {
let finalState;
let count = 0;
Expand Down Expand Up @@ -322,6 +325,178 @@ describe('RXJs operators', () => {
})();
});
});

describe('deglitchFalse', () => {
it('should change simple (0-->1)', function(done) {
inject([LoggerService], function(logger: LoggerService) {
logger.log('test: should change simple (0-->1)');
let finalState;
let count = 0;
const test = new Subject<boolean>();
test
.pipe(
deglitchFalse(100),
tap(state => {
logger.log('test: tap: ' + state + ' count: ' + count);
finalState = state;
if (count === 0) {
expect(state).toBe(false);
} else {
expect(state).toBe(true);
}
count++;
})
)
.subscribe({
complete: () => {
expect(finalState).toBe(true);
done();
}
});

setTimeout(() => test.next(false), 0);
setTimeout(() => test.next(true), 500);
setTimeout(() => test.complete(), 650);
})();
});

it('should NOT deglitch simple true (0-->1->0)', function(done) {
inject([LoggerService], function(logger: LoggerService) {
logger.log('test: should NOT deglitch simple true (0-->1->0)');
let finalState;
const test = new Subject<boolean>();
let count = 0;
test
.pipe(
deglitchFalse(100),
tap(state => {
finalState = state;
count++;
logger.log('test: tap: ' + state + ' count: ' + count);
})
)
.subscribe({
complete: () => {
expect(count).toBe(3);
expect(finalState).toBeFalsy();
done();
}
});
setTimeout(() => test.next(false), 0);
setTimeout(() => test.next(true), 500);
setTimeout(() => test.next(false), 550);
setTimeout(() => test.complete(), 650);
})();
});

it('should deglitch simple false (1-->0->1)', function(done) {
inject([LoggerService], function(logger: LoggerService) {
logger.log('test: should deglitch simple false (1-->0->1)');
let finalState;
const test = new Subject<boolean>();
let count = 0;
test
.pipe(
deglitchFalse(100),
tap(state => {
finalState = state;
count++;
logger.log('test: tap: ' + state + ' count: ' + count);
})
)
.subscribe({
complete: () => {
expect(count).toBe(1);
expect(finalState).toBe(true);
done();
}
});
setTimeout(() => test.next(true), 0);
setTimeout(() => test.next(false), 500);
setTimeout(() => test.next(true), 550);
setTimeout(() => test.complete(), 650);
})();
});

it('should deglitch double false (0-->1-->0->1)', function(done) {
inject([LoggerService], function(logger: LoggerService) {
let finalState;
let count = 0;
const test = new Subject<boolean>();
test
.pipe(
deglitchFalse(100),
tap(state => {
logger.log('test: tap: ' + state + ' count: ' + count);
finalState = state;
if (count === 0) {
expect(state).toBe(false);
}
if (count === 1) {
expect(state).toBe(true);
}
count++;
})
)
.subscribe({
complete: () => {
expect(count).toBe(2); // 0->1
expect(finalState).toBe(true);
done();
}
});

setTimeout(() => test.next(false), 0);
setTimeout(() => test.next(true), 500);
setTimeout(() => test.next(false), 650);
setTimeout(() => test.next(true), 700);
setTimeout(() => test.complete(), 750);
})();
});

fit('should NOT deglitch double true (1-->0-->1->0)', function(done) {
inject([LoggerService], function(logger: LoggerService) {
let finalState;
let count = 0;
const test = new Subject<boolean>();
test
.pipe(
deglitchFalse(100),
tap(state => {
logger.log('test: tap: ' + state + ' count: ' + count);
finalState = state;
if (count === 0) {
expect(state).toBe(true);
}
if (count === 1) {
expect(state).toBe(false);
}
if (count === 2) {
expect(state).toBe(true);
}
if (count === 3) {
expect(state).toBe(false);
}
count++;
})
)
.subscribe({
complete: () => {
expect(count).toBe(4); // 1->0->1->0
expect(finalState).toBe(false);
done();
}
});

setTimeout(() => test.next(true), 0);
setTimeout(() => test.next(false), 500);
setTimeout(() => test.next(true), 650);
setTimeout(() => test.next(false), 700);
setTimeout(() => test.complete(), 750);
})();
});

});
});

// Check logging disabled times
Expand Down
58 changes: 58 additions & 0 deletions projects/virtual-repeat-angular-lib/src/lib/rxjs.operators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,61 @@ export function deglitch(glitchSize: number) {
});
};
}

/**
* Remove spurious falses on a boolean observable.
* @param {number} glitchSize max size of the gitches (in miliseconds) to be removed.
*/
export function deglitchFalse(glitchSize: number) {
return (source: Observable<boolean>) => {
return new Observable(observer => {
let currentState: boolean;
let lastState: boolean;
let lastStateTime: number;

return source
.pipe(
flatMap((value: boolean) => {
// logger.log(`deglitchFalse: value: ${value} currentState: ${currentState} `);
lastStateTime = Date.now();
lastState = value;
if (currentState === undefined || (value === true && currentState !== value)) {
currentState = value;
return of(value);
}
if (value === currentState) {
return empty();
} else {
return of(value).pipe(
delay(glitchSize),
flatMap((value_: boolean) => {
const elapsed = Date.now() - lastStateTime;
// logger.log(`deglitchFalse -> delay elapsed: ${elapsed} value_: ${value_} lastState: ${lastState} currentState: ${currentState} `);

if (value_ !== lastState) {
if (lastState === currentState) {
// logger.log(`deglitchFalse -> delay lastState === currentState -> empty()`);
return empty();
} else {
// logger.log(`deglitchFalse -> delay elapsed: ${elapsed} lastState !== currentState -> ${lastState}`);
currentState = lastState;
return of(currentState);
}
}
// logger.log(`deglitchFalse -> delay value_ !== lastState -> ${value_}`);
if (elapsed < glitchSize) {
// logger.log(`deglitchFalse -> delay ${elapsed} < glitchSize -> empty()`);
return empty();
}
currentState = value_;
return of(currentState);
})
);
}
})
)
.subscribe(observer);
});
};
}

Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
} from 'rxjs/operators';
import { LoggerService } from './logger.service';
import { IVirtualRepeat } from './virtual-repeat.base';
import { deglitch } from './rxjs.operators';
import { deglitch, deglitchFalse } from './rxjs.operators';

export const SCROLL_STOP_TIME_THRESHOLD = 200; // in milliseconds

Expand Down Expand Up @@ -187,13 +187,13 @@ export class VirtualRepeatContainer implements AfterViewInit, OnDestroy {
private _processingSubject = new Subject<boolean>();
public processingRaw$ = this._processingSubject.pipe(
tap(state => {
console.log('processingRaw$ ' + state);
this.logger.log('processingRaw$ ' + state);
})
);
public processing$ = this._processingSubject.pipe(
deglitch(200),
deglitchFalse(500),
tap(state => {
console.log('processing$ ' + state);
this.logger.log('processing$ ' + state);
})
);

Expand Down

0 comments on commit faae8be

Please sign in to comment.