@bimeister/pupakit.calendar
Version:
PupaKit Calendar
157 lines • 26.5 kB
JavaScript
import '@angular/cdk/collections';
import '@angular/cdk/scrolling';
import { isNil } from '@bimeister/utilities';
import { Subject } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';
import { MONTHS_IN_YEAR } from '../constants/months-in-year.const';
import { SMALL_CALENDAR_CYCLE_SIZE_IN_YEARS } from '../constants/small-calendar-cycle-size-in-years.const';
import '../enums/month-index.enum';
import { getHeightForEachMonthInCalendarCycle } from '../functions/get-height-for-each-month-in-calendar-cycle.function';
import '../interfaces/calendar-virtual-scroll-config.interface';
function getCalendarCycleIndexByIndex(index) {
const yearIndex = Math.floor(index / MONTHS_IN_YEAR);
return Math.floor(yearIndex / SMALL_CALENDAR_CYCLE_SIZE_IN_YEARS);
}
function getDistanceToMonthInCycle(cycle, lastYear = SMALL_CALENDAR_CYCLE_SIZE_IN_YEARS, lastMonthIndex = 11) {
return cycle.reduce((total, year, yearIndex) => {
if (yearIndex > lastYear) {
return total;
}
const yearHeight = year.reduce((sum, monthHeight, monthIndex) => {
const isBeforeTargetMonth = yearIndex < lastYear || monthIndex < lastMonthIndex;
return isBeforeTargetMonth ? sum + monthHeight : sum;
}, 0);
return total + yearHeight;
}, 0);
}
export class CalendarVirtualScrollStrategy {
constructor(config) {
this.config = config;
this.index$ = new Subject();
this.cycleIndex = 0;
this.viewport = null;
this.scrolledIndexChange = this.index$.pipe(distinctUntilChanged());
this.cycleMonthsHeights = this.getCycleMonthHeights(0);
this.cycleHeight = getDistanceToMonthInCycle(this.cycleMonthsHeights);
}
attach(viewport) {
this.viewport = viewport;
this.viewport.setTotalContentSize(this.getViewportHeight(this.cycleHeight, this.config.yearsRange));
this.updateRenderedRange(this.viewport);
}
detach() {
this.index$.complete();
this.viewport = null;
}
onContentScrolled() {
if (isNil(this.viewport)) {
return;
}
this.updateRenderedRange(this.viewport);
}
scrollToIndex(index, behavior) {
if (isNil(this.viewport)) {
return;
}
const scrollOffset = this.getOffsetForIndex(index);
this.viewport.scrollToOffset(scrollOffset, behavior);
}
onDataLengthChanged() {
}
onContentRendered() {
}
onRenderedOffsetChanged() {
}
getOffsetForIndex(index) {
const monthIndex = index % MONTHS_IN_YEAR;
const year = (index - monthIndex) / MONTHS_IN_YEAR;
return this.getDistanceToMonthInScroll(year, monthIndex);
}
getIndexForOffset(offset) {
const remainderHeight = offset % this.cycleHeight;
const scrolledYearsCount = ((offset - remainderHeight) / this.cycleHeight) * SMALL_CALENDAR_CYCLE_SIZE_IN_YEARS;
let reminderHeightAccumulator = 0;
for (let yearIndex = 0; yearIndex < SMALL_CALENDAR_CYCLE_SIZE_IN_YEARS; yearIndex++) {
for (let monthIndex = 0; monthIndex < MONTHS_IN_YEAR; monthIndex++) {
reminderHeightAccumulator += this.cycleMonthsHeights[yearIndex][monthIndex];
const isEndMonth = reminderHeightAccumulator > remainderHeight;
if (isEndMonth) {
return (scrolledYearsCount + yearIndex) * MONTHS_IN_YEAR + monthIndex;
}
}
}
return this.config.yearsRange;
}
updateRenderedRange(viewport) {
const offset = viewport.measureScrollOffset();
const { start, end } = viewport.getRenderedRange();
const newRange = { start, end };
const firstVisibleIndex = this.getIndexForOffset(offset);
const startOffset = offset - this.getOffsetForIndex(start);
const endOffset = this.getOffsetForIndex(end) - offset - viewport.getViewportSize();
const isScrollUp = startOffset < this.config.bufferPx && start !== 0;
const isScrollDown = endOffset < this.config.bufferPx && end !== viewport.getDataLength();
const update = () => {
viewport.setRenderedRange(newRange);
viewport.setRenderedContentOffset(this.getOffsetForIndex(newRange.start));
this.index$.next(firstVisibleIndex);
this.updateViewportHeightByIndex(firstVisibleIndex);
};
if (isScrollUp) {
newRange.start = this.getRangeStartByOffset(offset, 2);
newRange.end = this.getRangeEndByOffset(offset);
update();
return;
}
if (isScrollDown) {
newRange.start = this.getRangeStartByOffset(offset);
newRange.end = this.getRangeEndByOffset(offset, 2);
update();
return;
}
update();
}
getRangeStartByOffset(offset, bufferFactor = 1) {
return Math.max(0, this.getIndexForOffset(offset - this.config.bufferPx * bufferFactor));
}
getRangeEndByOffset(offset, bufferFactor = 1) {
const itemsCount = this.viewport.getDataLength();
const bufferSizePx = this.config.bufferPx * bufferFactor;
const endOffset = offset + this.viewport.getViewportSize();
return Math.min(itemsCount, this.getIndexForOffset(endOffset + bufferSizePx));
}
getDistanceToMonthInScroll(year, monthIndex) {
const remainderYear = year % SMALL_CALENDAR_CYCLE_SIZE_IN_YEARS;
const remainderHeight = getDistanceToMonthInCycle(this.cycleMonthsHeights, remainderYear, monthIndex);
const fullCyclesCount = (year - remainderYear) / SMALL_CALENDAR_CYCLE_SIZE_IN_YEARS;
const fullCyclesHeight = fullCyclesCount * this.cycleHeight;
const distanceToMonth = fullCyclesHeight + remainderHeight;
return year === 0 ? distanceToMonth : distanceToMonth + this.config.dividerHeightPx;
}
updateViewportHeightByIndex(index) {
const newCycleIndex = getCalendarCycleIndexByIndex(index);
if (newCycleIndex === this.cycleIndex) {
return;
}
this.cycleIndex = newCycleIndex;
this.cycleMonthsHeights = this.getCycleMonthHeights(this.cycleIndex);
this.cycleHeight = getDistanceToMonthInCycle(this.cycleMonthsHeights);
this.viewport.setTotalContentSize(this.getViewportHeight(this.cycleHeight, this.config.yearsRange));
}
getCycleMonthHeights(cycleIndex) {
const startYear = this.config.startYear + cycleIndex * SMALL_CALENDAR_CYCLE_SIZE_IN_YEARS;
return getHeightForEachMonthInCalendarCycle({
labelHeightPx: this.config.labelHeightPx,
weekHeightPx: this.config.weekHeightPx,
dividerHeightPx: this.config.dividerHeightPx,
startWeekday: this.config.startWeekday,
startYear,
});
}
getViewportHeight(cycleHeight, yearsRange) {
return (cycleHeight * Math.ceil(yearsRange / SMALL_CALENDAR_CYCLE_SIZE_IN_YEARS) -
this.config.labelHeightPx -
this.config.dividerHeightPx * 2);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsZW5kYXItdmlydHVhbC1zY3JvbGwtc3RyYXRlZ3kuY2xhc3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZGVjbGFyYXRpb25zL2NsYXNzZXMvY2FsZW5kYXItdmlydHVhbC1zY3JvbGwtc3RyYXRlZ3kuY2xhc3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBMEIsMEJBQTBCLENBQUM7QUFDckQsT0FBZ0Usd0JBQXdCLENBQUM7QUFDekYsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzdDLE9BQU8sRUFBYyxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDM0MsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxrQ0FBa0MsRUFBRSxNQUFNLHVEQUF1RCxDQUFDO0FBQzNHLE9BQTJCLDJCQUEyQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxvQ0FBb0MsRUFBRSxNQUFNLG1FQUFtRSxDQUFDO0FBQ3pILE9BQTRDLHdEQUF3RCxDQUFDO0FBRXJHLFNBQVMsNEJBQTRCLENBQUMsS0FBYTtJQUNqRCxNQUFNLFNBQVMsR0FBVyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxjQUFjLENBQUMsQ0FBQztJQUU3RCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLGtDQUFrQyxDQUFDLENBQUM7QUFDcEUsQ0FBQztBQUVELFNBQVMseUJBQXlCLENBQ2hDLEtBQXFDLEVBQ3JDLFdBQW1CLGtDQUFrQyxFQUNyRCxtQkFBZ0Q7SUFFaEQsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBYSxFQUFFLElBQXVCLEVBQUUsU0FBaUIsRUFBRSxFQUFFO1FBQ2hGLElBQUksU0FBUyxHQUFHLFFBQVEsRUFBRTtZQUN4QixPQUFPLEtBQUssQ0FB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O0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBMaXN0UmFuZ2UgfSBmcm9tICdAYW5ndWxhci9jZGsvY29sbGVjdGlvbnMnO1xuaW1wb3J0IHsgQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0LCBWaXJ0dWFsU2Nyb2xsU3RyYXRlZ3kgfSBmcm9tICdAYW5ndWxhci9jZGsvc2Nyb2xsaW5nJztcbmltcG9ydCB7IGlzTmlsIH0gZnJvbSAnQGJpbWVpc3Rlci91dGlsaXRpZXMnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGlzdGluY3RVbnRpbENoYW5nZWQgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBNT05USFNfSU5fWUVBUiB9IGZyb20gJy4uL2NvbnN0YW50cy9tb250aHMtaW4teWVhci5jb25zdCc7XG5pbXBvcnQgeyBTTUFMTF9DQUxFTkRBUl9DWUNMRV9TSVpFX0lOX1lFQVJTIH0gZnJvbSAnLi4vY29uc3RhbnRzL3NtYWxsLWNhbGVuZGFyLWN5Y2xlLXNpemUtaW4teWVhcnMuY29uc3QnO1xuaW1wb3J0IHsgTW9udGhJbmRleCB9IGZyb20gJy4uL2VudW1zL21vbnRoLWluZGV4LmVudW0nO1xuaW1wb3J0IHsgZ2V0SGVpZ2h0Rm9yRWFjaE1vbnRoSW5DYWxlbmRhckN5Y2xlIH0gZnJvbSAnLi4vZnVuY3Rpb25zL2dldC1oZWlnaHQtZm9yLWVhY2gtbW9udGgtaW4tY2FsZW5kYXItY3ljbGUuZnVuY3Rpb24nO1xuaW1wb3J0IHsgQ2FsZW5kYXJWaXJ0dWFsU2Nyb2xsQ29uZmlnIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9jYWxlbmRhci12aXJ0dWFsLXNjcm9sbC1jb25maWcuaW50ZXJmYWNlJztcblxuZnVuY3Rpb24gZ2V0Q2FsZW5kYXJDeWNsZUluZGV4QnlJbmRleChpbmRleDogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgeWVhckluZGV4OiBudW1iZXIgPSBNYXRoLmZsb29yKGluZGV4IC8gTU9OVEhTX0lOX1lFQVIpO1xuXG4gIHJldHVybiBNYXRoLmZsb29yKHllYXJJbmRleCAvIFNNQUxMX0NBTEVOREFSX0NZQ0xFX1NJWkVfSU5fWUVBUlMpO1xufVxuXG5mdW5jdGlvbiBnZXREaXN0YW5jZVRvTW9udGhJbkN5Y2xlKFxuICBjeWNsZTogcmVhZG9ubHkgKHJlYWRvbmx5IG51bWJlcltdKVtdLFxuICBsYXN0WWVhcjogbnVtYmVyID0gU01BTExfQ0FMRU5EQVJfQ1lDTEVfU0laRV9JTl9ZRUFSUyxcbiAgbGFzdE1vbnRoSW5kZXg6IE1vbnRoSW5kZXggPSBNb250aEluZGV4LkRlY2VtYmVyXG4pOiBudW1iZXIge1xuICByZXR1cm4gY3ljbGUucmVkdWNlKCh0b3RhbDogbnVtYmVyLCB5ZWFyOiByZWFkb25seSBudW1iZXJbXSwgeWVhckluZGV4OiBudW1iZXIpID0+IHtcbiAgICBpZiAoeWVhckluZGV4ID4gbGFzdFllYXIpIHtcbiAgICAgIHJldHVybiB0b3RhbDtcbiAgICB9XG5cbiAgICBjb25zdCB5ZWFySGVpZ2h0OiBudW1iZXIgPSB5ZWFyLnJlZHVjZSgoc3VtOiBudW1iZXIsIG1vbnRoSGVpZ2h0OiBudW1iZXIsIG1vbnRoSW5kZXg6IE1vbnRoSW5kZXgpID0+IHtcbiAgICAgIGNvbnN0IGlzQmVmb3JlVGFyZ2V0TW9udGg6IGJvb2xlYW4gPSB5ZWFySW5kZXggPCBsYXN0WWVhciB8fCBtb250aEluZGV4IDwgbGFzdE1vbnRoSW5kZXg7XG5cbiAgICAgIHJldHVybiBpc0JlZm9yZVRhcmdldE1vbnRoID8gc3VtICsgbW9udGhIZWlnaHQgOiBzdW07XG4gICAgfSwgMCk7XG5cbiAgICByZXR1cm4gdG90YWwgKyB5ZWFySGVpZ2h0O1xuICB9LCAwKTtcbn1cblxuZXhwb3J0IGNsYXNzIENhbGVuZGFyVmlydHVhbFNjcm9sbFN0cmF0ZWd5IGltcGxlbWVudHMgVmlydHVhbFNjcm9sbFN0cmF0ZWd5IHtcbiAgcHJpdmF0ZSByZWFkb25seSBpbmRleCQ6IFN1YmplY3Q8bnVtYmVyPiA9IG5ldyBTdWJqZWN0PG51bWJlcj4oKTtcblxuICBwcml2YXRlIGN5Y2xlSW5kZXg6IG51bWJlciA9IDA7XG5cbiAgcHJpdmF0ZSB2aWV3cG9ydDogQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0IHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSBjeWNsZUhlaWdodDogbnVtYmVyO1xuXG4gIHB1YmxpYyByZWFkb25seSBzY3JvbGxlZEluZGV4Q2hhbmdlOiBPYnNlcnZhYmxlPG51bWJlcj4gPSB0aGlzLmluZGV4JC5waXBlKGRpc3RpbmN0VW50aWxDaGFuZ2VkKCkpO1xuXG4gIHByaXZhdGUgY3ljbGVNb250aHNIZWlnaHRzOiByZWFkb25seSAocmVhZG9ubHkgbnVtYmVyW10pW10gPSB0aGlzLmdldEN5Y2xlTW9udGhIZWlnaHRzKDApO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgY29uZmlnOiBDYWxlbmRhclZpcnR1YWxTY3JvbGxDb25maWcpIHtcbiAgICB0aGlzLmN5Y2xlSGVpZ2h0ID0gZ2V0RGlzdGFuY2VUb01vbnRoSW5DeWNsZSh0aGlzLmN5Y2xlTW9udGhzSGVpZ2h0cyk7XG4gIH1cblxuICBwdWJsaWMgYXR0YWNoKHZpZXdwb3J0OiBDZGtWaXJ0dWFsU2Nyb2xsVmlld3BvcnQpOiB2b2lkIHtcbiAgICB0aGlzLnZpZXdwb3J0ID0gdmlld3BvcnQ7XG4gICAgdGhpcy52aWV3cG9ydC5zZXRUb3RhbENvbnRlbnRTaXplKHRoaXMuZ2V0Vmlld3BvcnRIZWlnaHQodGhpcy5jeWNsZUhlaWdodCwgdGhpcy5jb25maWcueWVhcnNSYW5nZSkpO1xuICAgIHRoaXMudXBkYXRlUmVuZGVyZWRSYW5nZSh0aGlzLnZpZXdwb3J0KTtcbiAgfVxuXG4gIHB1YmxpYyBkZXRhY2goKTogdm9pZCB7XG4gICAgdGhpcy5pbmRleCQuY29tcGxldGUoKTtcbiAgICB0aGlzLnZpZXdwb3J0ID0gbnVsbDtcbiAgfVxuXG4gIHB1YmxpYyBvbkNvbnRlbnRTY3JvbGxlZCgpOiB2b2lkIHtcbiAgICBpZiAoaXNOaWwodGhpcy52aWV3cG9ydCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZVJlbmRlcmVkUmFuZ2UodGhpcy52aWV3cG9ydCk7XG4gIH1cblxuICBwdWJsaWMgc2Nyb2xsVG9JbmRleChpbmRleDogbnVtYmVyLCBiZWhhdmlvcjogU2Nyb2xsQmVoYXZpb3IpOiB2b2lkIHtcbiAgICBpZiAoaXNOaWwodGhpcy52aWV3cG9ydCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBzY3JvbGxPZmZzZXQ6IG51bWJlciA9IHRoaXMuZ2V0T2Zmc2V0Rm9ySW5kZXgoaW5kZXgpO1xuXG4gICAgdGhpcy52aWV3cG9ydC5zY3JvbGxUb09mZnNldChzY3JvbGxPZmZzZXQsIGJlaGF2aW9yKTtcbiAgfVxuXG4gIHB1YmxpYyBvbkRhdGFMZW5ndGhDaGFuZ2VkKCk6IHZvaWQge1xuICAgIC8vIG5vdCBuZWVkZWRcbiAgfVxuICBwdWJsaWMgb25Db250ZW50UmVuZGVyZWQoKTogdm9pZCB7XG4gICAgLy8gbm90IG5lZWRlZFxuICB9XG4gIHB1YmxpYyBvblJlbmRlcmVkT2Zmc2V0Q2hhbmdlZCgpOiB2b2lkIHtcbiAgICAvLyBub3QgbmVlZGVkXG4gIH1cblxuICBwcml2YXRlIGdldE9mZnNldEZvckluZGV4KGluZGV4OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IG1vbnRoSW5kZXg6IG51bWJlciA9IGluZGV4ICUgTU9OVEhTX0lOX1lFQVI7XG4gICAgY29uc3QgeWVhcjogbnVtYmVyID0gKGluZGV4IC0gbW9udGhJbmRleCkgLyBNT05USFNfSU5fWUVBUjtcblxuICAgIHJldHVybiB0aGlzLmdldERpc3RhbmNlVG9Nb250aEluU2Nyb2xsKHllYXIsIG1vbnRoSW5kZXgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRJbmRleEZvck9mZnNldChvZmZzZXQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgY29uc3QgcmVtYWluZGVySGVpZ2h0OiBudW1iZXIgPSBvZmZzZXQgJSB0aGlzLmN5Y2xlSGVpZ2h0O1xuXG4gICAgY29uc3Qgc2Nyb2xsZWRZZWFyc0NvdW50OiBudW1iZXIgPVxuICAgICAgKChvZmZzZXQgLSByZW1haW5kZXJIZWlnaHQpIC8gdGhpcy5jeWNsZUhlaWdodCkgKiBTTUFMTF9DQUxFTkRBUl9DWUNMRV9TSVpFX0lOX1lFQVJTO1xuXG4gICAgbGV0IHJlbWluZGVySGVpZ2h0QWNjdW11bGF0b3I6IG51bWJlciA9IDA7XG4gICAgZm9yIChsZXQgeWVhckluZGV4OiBudW1iZXIgPSAwOyB5ZWFySW5kZXggPCBTTUFMTF9DQUxFTkRBUl9DWUNMRV9TSVpFX0lOX1lFQVJTOyB5ZWFySW5kZXgrKykge1xuICAgICAgZm9yIChsZXQgbW9udGhJbmRleDogbnVtYmVyID0gMDsgbW9udGhJbmRleCA8IE1PTlRIU19JTl9ZRUFSOyBtb250aEluZGV4KyspIHtcbiAgICAgICAgcmVtaW5kZXJIZWlnaHRBY2N1bXVsYXRvciArPSB0aGlzLmN5Y2xlTW9udGhzSGVpZ2h0c1t5ZWFySW5kZXhdW21vbnRoSW5kZXhdO1xuXG4gICAgICAgIGNvbnN0IGlzRW5kTW9udGg6IGJvb2xlYW4gPSByZW1pbmRlckhlaWdodEFjY3VtdWxhdG9yID4gcmVtYWluZGVySGVpZ2h0O1xuXG4gICAgICAgIGlmIChpc0VuZE1vbnRoKSB7XG4gICAgICAgICAgcmV0dXJuIChzY3JvbGxlZFllYXJzQ291bnQgKyB5ZWFySW5kZXgpICogTU9OVEhTX0lOX1lFQVIgKyBtb250aEluZGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLnllYXJzUmFuZ2U7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVJlbmRlcmVkUmFuZ2Uodmlld3BvcnQ6IENka1ZpcnR1YWxTY3JvbGxWaWV3cG9ydCk6IHZvaWQge1xuICAgIGNvbnN0IG9mZnNldDogbnVtYmVyID0gdmlld3BvcnQubWVhc3VyZVNjcm9sbE9mZnNldCgpO1xuXG4gICAgY29uc3QgeyBzdGFydCwgZW5kIH06IExpc3RSYW5nZSA9IHZpZXdwb3J0LmdldFJlbmRlcmVkUmFuZ2UoKTtcblxuICAgIGNvbnN0IG5ld1JhbmdlOiBMaXN0UmFuZ2UgPSB7IHN0YXJ0LCBlbmQgfTtcblxuICAgIGNvbnN0IGZpcnN0VmlzaWJsZUluZGV4OiBudW1iZXIgPSB0aGlzLmdldEluZGV4Rm9yT2Zmc2V0KG9mZnNldCk7XG5cbiAgICBjb25zdCBzdGFydE9mZnNldDogbnVtYmVyID0gb2Zmc2V0IC0gdGhpcy5nZXRPZmZzZXRGb3JJbmRleChzdGFydCk7XG4gICAgY29uc3QgZW5kT2Zmc2V0OiBudW1iZXIgPSB0aGlzLmdldE9mZnNldEZvckluZGV4KGVuZCkgLSBvZmZzZXQgLSB2aWV3cG9ydC5nZXRWaWV3cG9ydFNpemUoKTtcblxuICAgIGNvbnN0IGlzU2Nyb2xsVXA6IGJvb2xlYW4gPSBzdGFydE9mZnNldCA8IHRoaXMuY29uZmlnLmJ1ZmZlclB4ICYmIHN0YXJ0ICE9PSAwO1xuICAgIGNvbnN0IGlzU2Nyb2xsRG93bjogYm9vbGVhbiA9IGVuZE9mZnNldCA8IHRoaXMuY29uZmlnLmJ1ZmZlclB4ICYmIGVuZCAhPT0gdmlld3BvcnQuZ2V0RGF0YUxlbmd0aCgpO1xuXG4gICAgY29uc3QgdXBkYXRlOiBWb2lkRnVuY3Rpb24gPSAoKSA9PiB7XG4gICAgICB2aWV3cG9ydC5zZXRSZW5kZXJlZFJhbmdlKG5ld1JhbmdlKTtcbiAgICAgIHZpZXdwb3J0LnNldFJlbmRlcmVkQ29udGVudE9mZnNldCh0aGlzLmdldE9mZnNldEZvckluZGV4KG5ld1JhbmdlLnN0YXJ0KSk7XG4gICAgICB0aGlzLmluZGV4JC5uZXh0KGZpcnN0VmlzaWJsZUluZGV4KTtcbiAgICAgIHRoaXMudXBkYXRlVmlld3BvcnRIZWlnaHRCeUluZGV4KGZpcnN0VmlzaWJsZUluZGV4KTtcbiAgICB9O1xuXG4gICAgaWYgKGlzU2Nyb2xsVXApIHtcbiAgICAgIG5ld1JhbmdlLnN0YXJ0ID0gdGhpcy5nZXRSYW5nZVN0YXJ0QnlPZmZzZXQob2Zmc2V0LCAyKTtcbiAgICAgIG5ld1JhbmdlLmVuZCA9IHRoaXMuZ2V0UmFuZ2VFbmRCeU9mZnNldChvZmZzZXQpO1xuXG4gICAgICB1cGRhdGUoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoaXNTY3JvbGxEb3duKSB7XG4gICAgICBuZXdSYW5nZS5zdGFydCA9IHRoaXMuZ2V0UmFuZ2VTdGFydEJ5T2Zmc2V0KG9mZnNldCk7XG4gICAgICBuZXdSYW5nZS5lbmQgPSB0aGlzLmdldFJhbmdlRW5kQnlPZmZzZXQob2Zmc2V0LCAyKTtcblxuICAgICAgdXBkYXRlKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdXBkYXRlKCk7XG4gIH1cblxuICBwcml2YXRlIGdldFJhbmdlU3RhcnRCeU9mZnNldChvZmZzZXQ6IG51bWJlciwgYnVmZmVyRmFjdG9yOiBudW1iZXIgPSAxKTogbnVtYmVyIHtcbiAgICByZXR1cm4gTWF0aC5tYXgoMCwgdGhpcy5nZXRJbmRleEZvck9mZnNldChvZmZzZXQgLSB0aGlzLmNvbmZpZy5idWZmZXJQeCAqIGJ1ZmZlckZhY3RvcikpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRSYW5nZUVuZEJ5T2Zmc2V0KG9mZnNldDogbnVtYmVyLCBidWZmZXJGYWN0b3I6IG51bWJlciA9IDEpOiBudW1iZXIge1xuICAgIGNvbnN0IGl0ZW1zQ291bnQ6IG51bWJlciA9IHRoaXMudmlld3BvcnQuZ2V0RGF0YUxlbmd0aCgpO1xuXG4gICAgY29uc3QgYnVmZmVyU2l6ZVB4OiBudW1iZXIgPSB0aGlzLmNvbmZpZy5idWZmZXJQeCAqIGJ1ZmZlckZhY3RvcjtcblxuICAgIGNvbnN0IGVuZE9mZnNldDogbnVtYmVyID0gb2Zmc2V0ICsgdGhpcy52aWV3cG9ydC5nZXRWaWV3cG9ydFNpemUoKTtcblxuICAgIHJldHVybiBNYXRoLm1pbihpdGVtc0NvdW50LCB0aGlzLmdldEluZGV4Rm9yT2Zmc2V0KGVuZE9mZnNldCArIGJ1ZmZlclNpemVQeCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREaXN0YW5jZVRvTW9udGhJblNjcm9sbCh5ZWFyOiBudW1iZXIsIG1vbnRoSW5kZXg/OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IHJlbWFpbmRlclllYXI6IG51bWJlciA9IHllYXIgJSBTTUFMTF9DQUxFTkRBUl9DWUNMRV9TSVpFX0lOX1lFQVJTO1xuXG4gICAgY29uc3QgcmVtYWluZGVySGVpZ2h0OiBudW1iZXIgPSBnZXREaXN0YW5jZVRvTW9udGhJbkN5Y2xlKHRoaXMuY3ljbGVNb250aHNIZWlnaHRzLCByZW1haW5kZXJZZWFyLCBtb250aEluZGV4KTtcblxuICAgIGNvbnN0IGZ1bGxDeWNsZXNDb3VudDogbnVtYmVyID0gKHllYXIgLSByZW1haW5kZXJZZWFyKSAvIFNNQUxMX0NBTEVOREFSX0NZQ0xFX1NJWkVfSU5fWUVBUlM7XG5cbiAgICBjb25zdCBmdWxsQ3ljbGVzSGVpZ2h0OiBudW1iZXIgPSBmdWxsQ3ljbGVzQ291bnQgKiB0aGlzLmN5Y2xlSGVpZ2h0O1xuXG4gICAgY29uc3QgZGlzdGFuY2VUb01vbnRoOiBudW1iZXIgPSBmdWxsQ3ljbGVzSGVpZ2h0ICsgcmVtYWluZGVySGVpZ2h0O1xuXG4gICAgcmV0dXJuIHllYXIgPT09IDAgPyBkaXN0YW5jZVRvTW9udGggOiBkaXN0YW5jZVRvTW9udGggKyB0aGlzLmNvbmZpZy5kaXZpZGVySGVpZ2h0UHg7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVZpZXdwb3J0SGVpZ2h0QnlJbmRleChpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgbmV3Q3ljbGVJbmRleDogbnVtYmVyID0gZ2V0Q2FsZW5kYXJDeWNsZUluZGV4QnlJbmRleChpbmRleCk7XG5cbiAgICBpZiAobmV3Q3ljbGVJbmRleCA9PT0gdGhpcy5jeWNsZUluZGV4KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5jeWNsZUluZGV4ID0gbmV3Q3ljbGVJbmRleDtcblxuICAgIHRoaXMuY3ljbGVNb250aHNIZWlnaHRzID0gdGhpcy5nZXRDeWNsZU1vbnRoSGVpZ2h0cyh0aGlzLmN5Y2xlSW5kZXgpO1xuICAgIHRoaXMuY3ljbGVIZWlnaHQgPSBnZXREaXN0YW5jZVRvTW9udGhJbkN5Y2xlKHRoaXMuY3ljbGVNb250aHNIZWlnaHRzKTtcblxuICAgIHRoaXMudmlld3BvcnQuc2V0VG90YWxDb250ZW50U2l6ZSh0aGlzLmdldFZpZXdwb3J0SGVpZ2h0KHRoaXMuY3ljbGVIZWlnaHQsIHRoaXMuY29uZmlnLnllYXJzUmFuZ2UpKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q3ljbGVNb250aEhlaWdodHMoY3ljbGVJbmRleDogbnVtYmVyKTogcmVhZG9ubHkgKHJlYWRvbmx5IG51bWJlcltdKVtdIHtcbiAgICBjb25zdCBzdGFydFllYXI6IG51bWJlciA9IHRoaXMuY29uZmlnLnN0YXJ0WWVhciArIGN5Y2xlSW5kZXggKiBTTUFMTF9DQUxFTkRBUl9DWUNMRV9TSVpFX0lOX1lFQVJTO1xuXG4gICAgcmV0dXJuIGdldEhlaWdodEZvckVhY2hNb250aEluQ2FsZW5kYXJDeWNsZSh7XG4gICAgICBsYWJlbEhlaWdodFB4OiB0aGlzLmNvbmZpZy5sYWJlbEhlaWdodFB4LFxuICAgICAgd2Vla0hlaWdodFB4OiB0aGlzLmNvbmZpZy53ZWVrSGVpZ2h0UHgsXG4gICAgICBkaXZpZGVySGVpZ2h0UHg6IHRoaXMuY29uZmlnLmRpdmlkZXJIZWlnaHRQeCxcbiAgICAgIHN0YXJ0V2Vla2RheTogdGhpcy5jb25maWcuc3RhcnRXZWVrZGF5LFxuICAgICAgc3RhcnRZZWFyLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRWaWV3cG9ydEhlaWdodChjeWNsZUhlaWdodDogbnVtYmVyLCB5ZWFyc1JhbmdlOiBudW1iZXIpOiBudW1iZXIge1xuICAgIHJldHVybiAoXG4gICAgICBjeWNsZUhlaWdodCAqIE1hdGguY2VpbCh5ZWFyc1JhbmdlIC8gU01BTExfQ0FMRU5EQVJfQ1lDTEVfU0laRV9JTl9ZRUFSUykgLVxuICAgICAgdGhpcy5jb25maWcubGFiZWxIZWlnaHRQeCAtXG4gICAgICB0aGlzLmNvbmZpZy5kaXZpZGVySGVpZ2h0UHggKiAyXG4gICAgKTtcbiAgfVxufVxuIl19