201 lines
25 KiB
JavaScript
201 lines
25 KiB
JavaScript
import { Directive, ElementRef, EventEmitter, forwardRef, HostBinding, HostListener, inject, Input, NgZone, Output, Renderer2, } from '@angular/core';
|
|
import { dndState, endDrag, startDrag } from './dnd-state';
|
|
import { calculateDragImageOffset, setDragData, setDragImage, } from './dnd-utils';
|
|
import * as i0 from "@angular/core";
|
|
class DndDragImageRefDirective {
|
|
dndDraggableDirective = inject(forwardRef(() => DndDraggableDirective));
|
|
elementRef = inject(ElementRef);
|
|
ngOnInit() {
|
|
this.dndDraggableDirective.registerDragImage(this.elementRef);
|
|
}
|
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: DndDragImageRefDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.1", type: DndDragImageRefDirective, isStandalone: true, selector: "[dndDragImageRef]", ngImport: i0 });
|
|
}
|
|
export { DndDragImageRefDirective };
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: DndDragImageRefDirective, decorators: [{
|
|
type: Directive,
|
|
args: [{ selector: '[dndDragImageRef]', standalone: true }]
|
|
}] });
|
|
class DndDraggableDirective {
|
|
dndDraggable;
|
|
dndEffectAllowed = 'copy';
|
|
dndType;
|
|
dndDraggingClass = 'dndDragging';
|
|
dndDraggingSourceClass = 'dndDraggingSource';
|
|
dndDraggableDisabledClass = 'dndDraggableDisabled';
|
|
dndDragImageOffsetFunction = calculateDragImageOffset;
|
|
dndStart = new EventEmitter();
|
|
dndDrag = new EventEmitter();
|
|
dndEnd = new EventEmitter();
|
|
dndMoved = new EventEmitter();
|
|
dndCopied = new EventEmitter();
|
|
dndLinked = new EventEmitter();
|
|
dndCanceled = new EventEmitter();
|
|
draggable = true;
|
|
dndHandle;
|
|
dndDragImageElementRef;
|
|
dragImage;
|
|
isDragStarted = false;
|
|
elementRef = inject(ElementRef);
|
|
renderer = inject(Renderer2);
|
|
ngZone = inject(NgZone);
|
|
set dndDisableIf(value) {
|
|
this.draggable = !value;
|
|
if (this.draggable) {
|
|
this.renderer.removeClass(this.elementRef.nativeElement, this.dndDraggableDisabledClass);
|
|
}
|
|
else {
|
|
this.renderer.addClass(this.elementRef.nativeElement, this.dndDraggableDisabledClass);
|
|
}
|
|
}
|
|
set dndDisableDragIf(value) {
|
|
this.dndDisableIf = value;
|
|
}
|
|
ngAfterViewInit() {
|
|
this.ngZone.runOutsideAngular(() => {
|
|
this.elementRef.nativeElement.addEventListener('drag', this.dragEventHandler);
|
|
});
|
|
}
|
|
ngOnDestroy() {
|
|
this.elementRef.nativeElement.removeEventListener('drag', this.dragEventHandler);
|
|
if (this.isDragStarted) {
|
|
endDrag();
|
|
}
|
|
}
|
|
onDragStart(event) {
|
|
if (!this.draggable) {
|
|
return false;
|
|
}
|
|
// check if there is dnd handle and if the dnd handle was used to start the drag
|
|
if (this.dndHandle != null && event._dndUsingHandle == null) {
|
|
event.stopPropagation();
|
|
return false;
|
|
}
|
|
// initialize global state
|
|
startDrag(event, this.dndEffectAllowed, this.dndType);
|
|
this.isDragStarted = true;
|
|
setDragData(event, { data: this.dndDraggable, type: this.dndType }, dndState.effectAllowed);
|
|
this.dragImage = this.determineDragImage();
|
|
// set dragging css class prior to setDragImage so styles are applied before
|
|
// TODO breaking change: add class to elementRef rather than drag image which could be another element
|
|
this.renderer.addClass(this.dragImage, this.dndDraggingClass);
|
|
// set custom dragimage if present
|
|
// set dragimage if drag is started from dndHandle
|
|
if (this.dndDragImageElementRef != null || event._dndUsingHandle != null) {
|
|
setDragImage(event, this.dragImage, this.dndDragImageOffsetFunction);
|
|
}
|
|
// add dragging source css class on first drag event
|
|
const unregister = this.renderer.listen(this.elementRef.nativeElement, 'drag', () => {
|
|
this.renderer.addClass(this.elementRef.nativeElement, this.dndDraggingSourceClass);
|
|
unregister();
|
|
});
|
|
this.dndStart.emit(event);
|
|
event.stopPropagation();
|
|
setTimeout(() => {
|
|
this.renderer.setStyle(this.dragImage, 'pointer-events', 'none');
|
|
}, 100);
|
|
return true;
|
|
}
|
|
onDrag(event) {
|
|
this.dndDrag.emit(event);
|
|
}
|
|
onDragEnd(event) {
|
|
if (!this.draggable || !this.isDragStarted) {
|
|
return;
|
|
}
|
|
// get drop effect from custom stored state as its not reliable across browsers
|
|
const dropEffect = dndState.dropEffect;
|
|
this.renderer.setStyle(this.dragImage, 'pointer-events', 'unset');
|
|
let dropEffectEmitter;
|
|
switch (dropEffect) {
|
|
case 'copy':
|
|
dropEffectEmitter = this.dndCopied;
|
|
break;
|
|
case 'link':
|
|
dropEffectEmitter = this.dndLinked;
|
|
break;
|
|
case 'move':
|
|
dropEffectEmitter = this.dndMoved;
|
|
break;
|
|
default:
|
|
dropEffectEmitter = this.dndCanceled;
|
|
break;
|
|
}
|
|
dropEffectEmitter.emit(event);
|
|
this.dndEnd.emit(event);
|
|
// reset global state
|
|
endDrag();
|
|
this.isDragStarted = false;
|
|
this.renderer.removeClass(this.dragImage, this.dndDraggingClass);
|
|
// IE9 special hammering
|
|
window.setTimeout(() => {
|
|
this.renderer.removeClass(this.elementRef.nativeElement, this.dndDraggingSourceClass);
|
|
}, 0);
|
|
event.stopPropagation();
|
|
}
|
|
registerDragHandle(handle) {
|
|
this.dndHandle = handle;
|
|
}
|
|
registerDragImage(elementRef) {
|
|
this.dndDragImageElementRef = elementRef;
|
|
}
|
|
dragEventHandler = (event) => this.onDrag(event);
|
|
determineDragImage() {
|
|
// evaluate custom drag image existence
|
|
if (typeof this.dndDragImageElementRef !== 'undefined') {
|
|
return this.dndDragImageElementRef.nativeElement;
|
|
}
|
|
else {
|
|
return this.elementRef.nativeElement;
|
|
}
|
|
}
|
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: DndDraggableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.1", type: DndDraggableDirective, isStandalone: true, selector: "[dndDraggable]", inputs: { dndDraggable: "dndDraggable", dndEffectAllowed: "dndEffectAllowed", dndType: "dndType", dndDraggingClass: "dndDraggingClass", dndDraggingSourceClass: "dndDraggingSourceClass", dndDraggableDisabledClass: "dndDraggableDisabledClass", dndDragImageOffsetFunction: "dndDragImageOffsetFunction", dndDisableIf: "dndDisableIf", dndDisableDragIf: "dndDisableDragIf" }, outputs: { dndStart: "dndStart", dndDrag: "dndDrag", dndEnd: "dndEnd", dndMoved: "dndMoved", dndCopied: "dndCopied", dndLinked: "dndLinked", dndCanceled: "dndCanceled" }, host: { listeners: { "dragstart": "onDragStart($event)", "dragend": "onDragEnd($event)" }, properties: { "attr.draggable": "this.draggable" } }, ngImport: i0 });
|
|
}
|
|
export { DndDraggableDirective };
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: DndDraggableDirective, decorators: [{
|
|
type: Directive,
|
|
args: [{ selector: '[dndDraggable]', standalone: true }]
|
|
}], propDecorators: { dndDraggable: [{
|
|
type: Input
|
|
}], dndEffectAllowed: [{
|
|
type: Input
|
|
}], dndType: [{
|
|
type: Input
|
|
}], dndDraggingClass: [{
|
|
type: Input
|
|
}], dndDraggingSourceClass: [{
|
|
type: Input
|
|
}], dndDraggableDisabledClass: [{
|
|
type: Input
|
|
}], dndDragImageOffsetFunction: [{
|
|
type: Input
|
|
}], dndStart: [{
|
|
type: Output
|
|
}], dndDrag: [{
|
|
type: Output
|
|
}], dndEnd: [{
|
|
type: Output
|
|
}], dndMoved: [{
|
|
type: Output
|
|
}], dndCopied: [{
|
|
type: Output
|
|
}], dndLinked: [{
|
|
type: Output
|
|
}], dndCanceled: [{
|
|
type: Output
|
|
}], draggable: [{
|
|
type: HostBinding,
|
|
args: ['attr.draggable']
|
|
}], dndDisableIf: [{
|
|
type: Input
|
|
}], dndDisableDragIf: [{
|
|
type: Input
|
|
}], onDragStart: [{
|
|
type: HostListener,
|
|
args: ['dragstart', ['$event']]
|
|
}], onDragEnd: [{
|
|
type: HostListener,
|
|
args: ['dragend', ['$event']]
|
|
}] } });
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG5kLWRyYWdnYWJsZS5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9kbmQvc3JjL2xpYi9kbmQtZHJhZ2dhYmxlLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUwsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osVUFBVSxFQUNWLFdBQVcsRUFDWCxZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFDTCxNQUFNLEVBR04sTUFBTSxFQUNOLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFM0QsT0FBTyxFQUNMLHdCQUF3QixFQUd4QixXQUFXLEVBQ1gsWUFBWSxHQUNiLE1BQU0sYUFBYSxDQUFDOztBQUVyQixNQUNhLHdCQUF3QjtJQUNuQyxxQkFBcUIsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQztJQUN4RSxVQUFVLEdBQTRCLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUV6RCxRQUFRO1FBQ04sSUFBSSxDQUFDLHFCQUFxQixDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNoRSxDQUFDO3VHQU5VLHdCQUF3QjsyRkFBeEIsd0JBQXdCOztTQUF4Qix3QkFBd0I7MkZBQXhCLHdCQUF3QjtrQkFEcEMsU0FBUzttQkFBQyxFQUFFLFFBQVEsRUFBRSxtQkFBbUIsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFOztBQVU5RCxNQUNhLHFCQUFxQjtJQUN2QixZQUFZLENBQU07SUFDbEIsZ0JBQWdCLEdBQWtCLE1BQU0sQ0FBQztJQUN6QyxPQUFPLENBQVU7SUFDakIsZ0JBQWdCLEdBQUcsYUFBYSxDQUFDO0lBQ2pDLHNCQUFzQixHQUFHLG1CQUFtQixDQUFDO0lBQzdDLHlCQUF5QixHQUFHLHNCQUFzQixDQUFDO0lBQ25ELDBCQUEwQixHQUNqQyx3QkFBd0IsQ0FBQztJQUVSLFFBQVEsR0FDekIsSUFBSSxZQUFZLEVBQWEsQ0FBQztJQUNiLE9BQU8sR0FDeEIsSUFBSSxZQUFZLEVBQWEsQ0FBQztJQUNiLE1BQU0sR0FDdkIsSUFBSSxZQUFZLEVBQWEsQ0FBQztJQUNiLFFBQVEsR0FDekIsSUFBSSxZQUFZLEVBQWEsQ0FBQztJQUNiLFNBQVMsR0FDMUIsSUFBSSxZQUFZLEVBQWEsQ0FBQztJQUNiLFNBQVMsR0FDMUIsSUFBSSxZQUFZLEVBQWEsQ0FBQztJQUNiLFdBQVcsR0FDNUIsSUFBSSxZQUFZLEVBQWEsQ0FBQztJQUVELFNBQVMsR0FBRyxJQUFJLENBQUM7SUFFeEMsU0FBUyxDQUFzQjtJQUMvQixzQkFBc0IsQ0FBYztJQUNwQyxTQUFTLENBQXNCO0lBQy9CLGFBQWEsR0FBWSxLQUFLLENBQUM7SUFFL0IsVUFBVSxHQUE0QixNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDekQsUUFBUSxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUM3QixNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRWhDLElBQWEsWUFBWSxDQUFDLEtBQWM7UUFDdEMsSUFBSSxDQUFDLFNBQVMsR0FBRyxDQUFDLEtBQUssQ0FBQztRQUV4QixJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDbEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQ3ZCLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUM3QixJQUFJLENBQUMseUJBQXlCLENBQy9CLENBQUM7U0FDSDthQUFNO1lBQ0wsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQ3BCLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUM3QixJQUFJLENBQUMseUJBQXlCLENBQy9CLENBQUM7U0FDSDtJQUNILENBQUM7SUFFRCxJQUFhLGdCQUFnQixDQUFDLEtBQWM7UUFDMUMsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7SUFDNUIsQ0FBQztJQUVELGVBQWU7UUFDYixJQUFJLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRTtZQUNqQyxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FDNUMsTUFBTSxFQUNOLElBQUksQ0FBQyxnQkFBZ0IsQ0FDdEIsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxtQkFBbUIsQ0FDL0MsTUFBTSxFQUNOLElBQUksQ0FBQyxnQkFBZ0IsQ0FDdEIsQ0FBQztRQUNGLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRTtZQUN0QixPQUFPLEVBQUUsQ0FBQztTQUNYO0lBQ0gsQ0FBQztJQUVzQyxXQUFXLENBQUMsS0FBZTtRQUNoRSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNuQixPQUFPLEtBQUssQ0FBQztTQUNkO1FBRUQsZ0ZBQWdGO1FBQ2hGLElBQUksSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLElBQUksS0FBSyxDQUFDLGVBQWUsSUFBSSxJQUFJLEVBQUU7WUFDM0QsS0FBSyxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3hCLE9BQU8sS0FBSyxDQUFDO1NBQ2Q7UUFFRCwwQkFBMEI7UUFDMUIsU0FBUyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXRELElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO1FBRTFCLFdBQVcsQ0FDVCxLQUFLLEVBQ0wsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFlBQVksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUMvQyxRQUFRLENBQUMsYUFBYyxDQUN4QixDQUFDO1FBRUYsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUUzQyw0RUFBNEU7UUFDNUUsc0dBQXNHO1FBQ3RHLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFFOUQsa0NBQWtDO1FBQ2xDLGtEQUFrRDtRQUNsRCxJQUFJLElBQUksQ0FBQyxzQkFBc0IsSUFBSSxJQUFJLElBQUksS0FBSyxDQUFDLGVBQWUsSUFBSSxJQUFJLEVBQUU7WUFDeEUsWUFBWSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1NBQ3RFO1FBRUQsb0RBQW9EO1FBQ3BELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUNyQyxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsRUFDN0IsTUFBTSxFQUNOLEdBQUcsRUFBRTtZQUNILElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUNwQixJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsRUFDN0IsSUFBSSxDQUFDLHNCQUFzQixDQUM1QixDQUFDO1lBQ0YsVUFBVSxFQUFFLENBQUM7UUFDZixDQUFDLENBQ0YsQ0FBQztRQUVGLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRTFCLEtBQUssQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUV4QixVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ2QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNuRSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFFUixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxNQUFNLENBQUMsS0FBZ0I7UUFDckIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0IsQ0FBQztJQUVvQyxTQUFTLENBQUMsS0FBZ0I7UUFDN0QsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFO1lBQzFDLE9BQU87U0FDUjtRQUNELCtFQUErRTtRQUMvRSxNQUFNLFVBQVUsR0FBRyxRQUFRLENBQUMsVUFBVSxDQUFDO1FBRXZDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsZ0JBQWdCLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFbEUsSUFBSSxpQkFBMEMsQ0FBQztRQUUvQyxRQUFRLFVBQVUsRUFBRTtZQUNsQixLQUFLLE1BQU07Z0JBQ1QsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztnQkFDbkMsTUFBTTtZQUVSLEtBQUssTUFBTTtnQkFDVCxpQkFBaUIsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUNuQyxNQUFNO1lBRVIsS0FBSyxNQUFNO2dCQUNULGlCQUFpQixHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7Z0JBQ2xDLE1BQU07WUFFUjtnQkFDRSxpQkFBaUIsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO2dCQUNyQyxNQUFNO1NBQ1Q7UUFFRCxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDOUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFeEIscUJBQXFCO1FBQ3JCLE9BQU8sRUFBRSxDQUFDO1FBRVYsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7UUFFM0IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUVqRSx3QkFBd0I7UUFDeEIsTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDckIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQ3ZCLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUM3QixJQUFJLENBQUMsc0JBQXNCLENBQzVCLENBQUM7UUFDSixDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFTixLQUFLLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVELGtCQUFrQixDQUFDLE1BQXNDO1FBQ3ZELElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxDQUFDO0lBQzFCLENBQUM7SUFFRCxpQkFBaUIsQ0FBQyxVQUFrQztRQUNsRCxJQUFJLENBQUMsc0JBQXNCLEdBQUcsVUFBVSxDQUFDO0lBQzNDLENBQUM7SUFFZ0IsZ0JBQWdCLEdBQStCLENBQzlELEtBQWdCLEVBQ2hCLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRWhCLGtCQUFrQjtRQUN4Qix1Q0FBdUM7UUFDdkMsSUFBSSxPQUFPLElBQUksQ0FBQyxzQkFBc0IsS0FBSyxXQUFXLEVBQUU7WUFDdEQsT0FBTyxJQUFJLENBQUMsc0JBQXNCLENBQUMsYUFBd0IsQ0FBQztTQUM3RDthQUFNO1lBQ0wsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQztTQUN0QztJQUNILENBQUM7dUdBOU1VLHFCQUFxQjsyRkFBckIscUJBQXFCOztTQUFyQixxQkFBcUI7MkZBQXJCLHFCQUFxQjtrQkFEakMsU0FBUzttQkFBQyxFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFOzhCQUVoRCxZQUFZO3NCQUFwQixLQUFLO2dCQUNHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFDRyxPQUFPO3NCQUFmLEtBQUs7Z0JBQ0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUNHLHNCQUFzQjtzQkFBOUIsS0FBSztnQkFDRyx5QkFBeUI7c0JBQWpDLEtBQUs7Z0JBQ0csMEJBQTBCO3NCQUFsQyxLQUFLO2dCQUdhLFFBQVE7c0JBQTFCLE1BQU07Z0JBRVksT0FBTztzQkFBekIsTUFBTTtnQkFFWSxNQUFNO3NCQUF4QixNQUFNO2dCQUVZLFFBQVE7c0JBQTFCLE1BQU07Z0JBRVksU0FBUztzQkFBM0IsTUFBTTtnQkFFWSxTQUFTO3NCQUEzQixNQUFNO2dCQUVZLFdBQVc7c0JBQTdCLE1BQU07Z0JBR3dCLFNBQVM7c0JBQXZDLFdBQVc7dUJBQUMsZ0JBQWdCO2dCQVdoQixZQUFZO3NCQUF4QixLQUFLO2dCQWdCTyxnQkFBZ0I7c0JBQTVCLEtBQUs7Z0JBdUJpQyxXQUFXO3NCQUFqRCxZQUFZO3VCQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkE4REEsU0FBUztzQkFBN0MsWUFBWTt1QkFBQyxTQUFTLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBEaXJlY3RpdmUsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgZm9yd2FyZFJlZixcbiAgSG9zdEJpbmRpbmcsXG4gIEhvc3RMaXN0ZW5lcixcbiAgaW5qZWN0LFxuICBJbnB1dCxcbiAgTmdab25lLFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICBSZW5kZXJlcjIsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRG5kSGFuZGxlRGlyZWN0aXZlIH0gZnJvbSAnLi9kbmQtaGFuZGxlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBkbmRTdGF0ZSwgZW5kRHJhZywgc3RhcnREcmFnIH0gZnJvbSAnLi9kbmQtc3RhdGUnO1xuaW1wb3J0IHsgRWZmZWN0QWxsb3dlZCB9IGZyb20gJy4vZG5kLXR5cGVzJztcbmltcG9ydCB7XG4gIGNhbGN1bGF0ZURyYWdJbWFnZU9mZnNldCxcbiAgRG5kRHJhZ0ltYWdlT2Zmc2V0RnVuY3Rpb24sXG4gIERuZEV2ZW50LFxuICBzZXREcmFnRGF0YSxcbiAgc2V0RHJhZ0ltYWdlLFxufSBmcm9tICcuL2RuZC11dGlscyc7XG5cbkBEaXJlY3RpdmUoeyBzZWxlY3RvcjogJ1tkbmREcmFnSW1hZ2VSZWZdJywgc3RhbmRhbG9uZTogdHJ1ZSB9KVxuZXhwb3J0IGNsYXNzIERuZERyYWdJbWFnZVJlZkRpcmVjdGl2ZSBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIGRuZERyYWdnYWJsZURpcmVjdGl2ZSA9IGluamVjdChmb3J3YXJkUmVmKCgpID0+IERuZERyYWdnYWJsZURpcmVjdGl2ZSkpO1xuICBlbGVtZW50UmVmOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PiA9IGluamVjdChFbGVtZW50UmVmKTtcblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmRuZERyYWdnYWJsZURpcmVjdGl2ZS5yZWdpc3RlckRyYWdJbWFnZSh0aGlzLmVsZW1lbnRSZWYpO1xuICB9XG59XG5cbkBEaXJlY3RpdmUoeyBzZWxlY3RvcjogJ1tkbmREcmFnZ2FibGVdJywgc3RhbmRhbG9uZTogdHJ1ZSB9KVxuZXhwb3J0IGNsYXNzIERuZERyYWdnYWJsZURpcmVjdGl2ZSBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG4gIEBJbnB1dCgpIGRuZERyYWdnYWJsZTogYW55O1xuICBASW5wdXQoKSBkbmRFZmZlY3RBbGxvd2VkOiBFZmZlY3RBbGxvd2VkID0gJ2NvcHknO1xuICBASW5wdXQoKSBkbmRUeXBlPzogc3RyaW5nO1xuICBASW5wdXQoKSBkbmREcmFnZ2luZ0NsYXNzID0gJ2RuZERyYWdnaW5nJztcbiAgQElucHV0KCkgZG5kRHJhZ2dpbmdTb3VyY2VDbGFzcyA9ICdkbmREcmFnZ2luZ1NvdXJjZSc7XG4gIEBJbnB1dCgpIGRuZERyYWdnYWJsZURpc2FibGVkQ2xhc3MgPSAnZG5kRHJhZ2dhYmxlRGlzYWJsZWQnO1xuICBASW5wdXQoKSBkbmREcmFnSW1hZ2VPZmZzZXRGdW5jdGlvbjogRG5kRHJhZ0ltYWdlT2Zmc2V0RnVuY3Rpb24gPVxuICAgIGNhbGN1bGF0ZURyYWdJbWFnZU9mZnNldDtcblxuICBAT3V0cHV0KCkgcmVhZG9ubHkgZG5kU3RhcnQ6IEV2ZW50RW1pdHRlcjxEcmFnRXZlbnQ+ID1cbiAgICBuZXcgRXZlbnRFbWl0dGVyPERyYWdFdmVudD4oKTtcbiAgQE91dHB1dCgpIHJlYWRvbmx5IGRuZERyYWc6IEV2ZW50RW1pdHRlcjxEcmFnRXZlbnQ+ID1cbiAgICBuZXcgRXZlbnRFbWl0dGVyPERyYWdFdmVudD4oKTtcbiAgQE91dHB1dCgpIHJlYWRvbmx5IGRuZEVuZDogRXZlbnRFbWl0dGVyPERyYWdFdmVudD4gPVxuICAgIG5ldyBFdmVudEVtaXR0ZXI8RHJhZ0V2ZW50PigpO1xuICBAT3V0cHV0KCkgcmVhZG9ubHkgZG5kTW92ZWQ6IEV2ZW50RW1pdHRlcjxEcmFnRXZlbnQ+ID1cbiAgICBuZXcgRXZlbnRFbWl0dGVyPERyYWdFdmVudD4oKTtcbiAgQE91dHB1dCgpIHJlYWRvbmx5IGRuZENvcGllZDogRXZlbnRFbWl0dGVyPERyYWdFdmVudD4gPVxuICAgIG5ldyBFdmVudEVtaXR0ZXI8RHJhZ0V2ZW50PigpO1xuICBAT3V0cHV0KCkgcmVhZG9ubHkgZG5kTGlua2VkOiBFdmVudEVtaXR0ZXI8RHJhZ0V2ZW50PiA9XG4gICAgbmV3IEV2ZW50RW1pdHRlcjxEcmFnRXZlbnQ+KCk7XG4gIEBPdXRwdXQoKSByZWFkb25seSBkbmRDYW5jZWxlZDogRXZlbnRFbWl0dGVyPERyYWdFdmVudD4gPVxuICAgIG5ldyBFdmVudEVtaXR0ZXI8RHJhZ0V2ZW50PigpO1xuXG4gIEBIb3N0QmluZGluZygnYXR0ci5kcmFnZ2FibGUnKSBkcmFnZ2FibGUgPSB0cnVlO1xuXG4gIHByaXZhdGUgZG5kSGFuZGxlPzogRG5kSGFuZGxlRGlyZWN0aXZlO1xuICBwcml2YXRlIGRuZERyYWdJbWFnZUVsZW1lbnRSZWY/OiBFbGVtZW50UmVmO1xuICBwcml2YXRlIGRyYWdJbWFnZTogRWxlbWVudCB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBpc0RyYWdTdGFydGVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgcHJpdmF0ZSBlbGVtZW50UmVmOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PiA9IGluamVjdChFbGVtZW50UmVmKTtcbiAgcHJpdmF0ZSByZW5kZXJlciA9IGluamVjdChSZW5kZXJlcjIpO1xuICBwcml2YXRlIG5nWm9uZSA9IGluamVjdChOZ1pvbmUpO1xuXG4gIEBJbnB1dCgpIHNldCBkbmREaXNhYmxlSWYodmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLmRyYWdnYWJsZSA9ICF2YWx1ZTtcblxuICAgIGlmICh0aGlzLmRyYWdnYWJsZSkge1xuICAgICAgdGhpcy5yZW5kZXJlci5yZW1vdmVDbGFzcyhcbiAgICAgICAgdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsXG4gICAgICAgIHRoaXMuZG5kRHJhZ2dhYmxlRGlzYWJsZWRDbGFzc1xuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyhcbiAgICAgICAgdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsXG4gICAgICAgIHRoaXMuZG5kRHJhZ2dhYmxlRGlzYWJsZWRDbGFzc1xuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBASW5wdXQoKSBzZXQgZG5kRGlzYWJsZURyYWdJZih2YWx1ZTogYm9vbGVhbikge1xuICAgIHRoaXMuZG5kRGlzYWJsZUlmID0gdmFsdWU7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgdGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgJ2RyYWcnLFxuICAgICAgICB0aGlzLmRyYWdFdmVudEhhbmRsZXJcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFxuICAgICAgJ2RyYWcnLFxuICAgICAgdGhpcy5kcmFnRXZlbnRIYW5kbGVyXG4gICAgKTtcbiAgICBpZiAodGhpcy5pc0RyYWdTdGFydGVkKSB7XG4gICAgICBlbmREcmFnKCk7XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZHJhZ3N0YXJ0JywgWyckZXZlbnQnXSkgb25EcmFnU3RhcnQoZXZlbnQ6IERuZEV2ZW50KTogYm9vbGVhbiB7XG4gICAgaWYgKCF0aGlzLmRyYWdnYWJsZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIGNoZWNrIGlmIHRoZXJlIGlzIGRuZCBoYW5kbGUgYW5kIGlmIHRoZSBkbmQgaGFuZGxlIHdhcyB1c2VkIHRvIHN0YXJ0IHRoZSBkcmFnXG4gICAgaWYgKHRoaXMuZG5kSGFuZGxlICE9IG51bGwgJiYgZXZlbnQuX2RuZFVzaW5nSGFuZGxlID09IG51bGwpIHtcbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIGluaXRpYWxpemUgZ2xvYmFsIHN0YXRlXG4gICAgc3RhcnREcmFnKGV2ZW50LCB0aGlzLmRuZEVmZmVjdEFsbG93ZWQsIHRoaXMuZG5kVHlwZSk7XG5cbiAgICB0aGlzLmlzRHJhZ1N0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgc2V0RHJhZ0RhdGEoXG4gICAgICBldmVudCxcbiAgICAgIHsgZGF0YTogdGhpcy5kbmREcmFnZ2FibGUsIHR5cGU6IHRoaXMuZG5kVHlwZSB9LFxuICAgICAgZG5kU3RhdGUuZWZmZWN0QWxsb3dlZCFcbiAgICApO1xuXG4gICAgdGhpcy5kcmFnSW1hZ2UgPSB0aGlzLmRldGVybWluZURyYWdJbWFnZSgpO1xuXG4gICAgLy8gc2V0IGRyYWdnaW5nIGNzcyBjbGFzcyBwcmlvciB0byBzZXREcmFnSW1hZ2Ugc28gc3R5bGVzIGFyZSBhcHBsaWVkIGJlZm9yZVxuICAgIC8vIFRPRE8gYnJlYWtpbmcgY2hhbmdlOiBhZGQgY2xhc3MgdG8gZWxlbWVudFJlZiByYXRoZXIgdGhhbiBkcmFnIGltYWdlIHdoaWNoIGNvdWxkIGJlIGFub3RoZXIgZWxlbWVudFxuICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3ModGhpcy5kcmFnSW1hZ2UsIHRoaXMuZG5kRHJhZ2dpbmdDbGFzcyk7XG5cbiAgICAvLyBzZXQgY3VzdG9tIGRyYWdpbWFnZSBpZiBwcmVzZW50XG4gICAgLy8gc2V0IGRyYWdpbWFnZSBpZiBkcmFnIGlzIHN0YXJ0ZWQgZnJvbSBkbmRIYW5kbGVcbiAgICBpZiAodGhpcy5kbmREcmFnSW1hZ2VFbGVtZW50UmVmICE9IG51bGwgfHwgZXZlbnQuX2RuZFVzaW5nSGFuZGxlICE9IG51bGwpIHtcbiAgICAgIHNldERyYWdJbWFnZShldmVudCwgdGhpcy5kcmFnSW1hZ2UsIHRoaXMuZG5kRHJhZ0ltYWdlT2Zmc2V0RnVuY3Rpb24pO1xuICAgIH1cblxuICAgIC8vIGFkZCBkcmFnZ2luZyBzb3VyY2UgY3NzIGNsYXNzIG9uIGZpcnN0IGRyYWcgZXZlbnRcbiAgICBjb25zdCB1bnJlZ2lzdGVyID0gdGhpcy5yZW5kZXJlci5saXN0ZW4oXG4gICAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCxcbiAgICAgICdkcmFnJyxcbiAgICAgICgpID0+IHtcbiAgICAgICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyhcbiAgICAgICAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCxcbiAgICAgICAgICB0aGlzLmRuZERyYWdnaW5nU291cmNlQ2xhc3NcbiAgICAgICAgKTtcbiAgICAgICAgdW5yZWdpc3RlcigpO1xuICAgICAgfVxuICAgICk7XG5cbiAgICB0aGlzLmRuZFN0YXJ0LmVtaXQoZXZlbnQpO1xuXG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5kcmFnSW1hZ2UsICdwb2ludGVyLWV2ZW50cycsICdub25lJyk7XG4gICAgfSwgMTAwKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgb25EcmFnKGV2ZW50OiBEcmFnRXZlbnQpIHtcbiAgICB0aGlzLmRuZERyYWcuZW1pdChldmVudCk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkcmFnZW5kJywgWyckZXZlbnQnXSkgb25EcmFnRW5kKGV2ZW50OiBEcmFnRXZlbnQpIHtcbiAgICBpZiAoIXRoaXMuZHJhZ2dhYmxlIHx8ICF0aGlzLmlzRHJhZ1N0YXJ0ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gZ2V0IGRyb3AgZWZmZWN0IGZyb20gY3VzdG9tIHN0b3JlZCBzdGF0ZSBhcyBpdHMgbm90IHJlbGlhYmxlIGFjcm9zcyBicm93c2Vyc1xuICAgIGNvbnN0IGRyb3BFZmZlY3QgPSBkbmRTdGF0ZS5kcm9wRWZmZWN0O1xuXG4gICAgdGhpcy5yZW5kZXJlci5zZXRTdHlsZSh0aGlzLmRyYWdJbWFnZSwgJ3BvaW50ZXItZXZlbnRzJywgJ3Vuc2V0Jyk7XG5cbiAgICBsZXQgZHJvcEVmZmVjdEVtaXR0ZXI6IEV2ZW50RW1pdHRlcjxEcmFnRXZlbnQ+O1xuXG4gICAgc3dpdGNoIChkcm9wRWZmZWN0KSB7XG4gICAgICBjYXNlICdjb3B5JzpcbiAgICAgICAgZHJvcEVmZmVjdEVtaXR0ZXIgPSB0aGlzLmRuZENvcGllZDtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ2xpbmsnOlxuICAgICAgICBkcm9wRWZmZWN0RW1pdHRlciA9IHRoaXMuZG5kTGlua2VkO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnbW92ZSc6XG4gICAgICAgIGRyb3BFZmZlY3RFbWl0dGVyID0gdGhpcy5kbmRNb3ZlZDtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGRyb3BFZmZlY3RFbWl0dGVyID0gdGhpcy5kbmRDYW5jZWxlZDtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgZHJvcEVmZmVjdEVtaXR0ZXIuZW1pdChldmVudCk7XG4gICAgdGhpcy5kbmRFbmQuZW1pdChldmVudCk7XG5cbiAgICAvLyByZXNldCBnbG9iYWwgc3RhdGVcbiAgICBlbmREcmFnKCk7XG5cbiAgICB0aGlzLmlzRHJhZ1N0YXJ0ZWQgPSBmYWxzZTtcblxuICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2xhc3ModGhpcy5kcmFnSW1hZ2UsIHRoaXMuZG5kRHJhZ2dpbmdDbGFzcyk7XG5cbiAgICAvLyBJRTkgc3BlY2lhbCBoYW1tZXJpbmdcbiAgICB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLnJlbmRlcmVyLnJlbW92ZUNsYXNzKFxuICAgICAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCxcbiAgICAgICAgdGhpcy5kbmREcmFnZ2luZ1NvdXJjZUNsYXNzXG4gICAgICApO1xuICAgIH0sIDApO1xuXG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cblxuICByZWdpc3RlckRyYWdIYW5kbGUoaGFuZGxlOiBEbmRIYW5kbGVEaXJlY3RpdmUgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLmRuZEhhbmRsZSA9IGhhbmRsZTtcbiAgfVxuXG4gIHJlZ2lzdGVyRHJhZ0ltYWdlKGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLmRuZERyYWdJbWFnZUVsZW1lbnRSZWYgPSBlbGVtZW50UmVmO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkcmFnRXZlbnRIYW5kbGVyOiAoZXZlbnQ6IERyYWdFdmVudCkgPT4gdm9pZCA9IChcbiAgICBldmVudDogRHJhZ0V2ZW50XG4gICkgPT4gdGhpcy5vbkRyYWcoZXZlbnQpO1xuXG4gIHByaXZhdGUgZGV0ZXJtaW5lRHJhZ0ltYWdlKCk6IEVsZW1lbnQge1xuICAgIC8vIGV2YWx1YXRlIGN1c3RvbSBkcmFnIGltYWdlIGV4aXN0ZW5jZVxuICAgIGlmICh0eXBlb2YgdGhpcy5kbmREcmFnSW1hZ2VFbGVtZW50UmVmICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIHRoaXMuZG5kRHJhZ0ltYWdlRWxlbWVudFJlZi5uYXRpdmVFbGVtZW50IGFzIEVsZW1lbnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
|