UNPKG

@bespunky/angular-zen

Version:

The Angular tools you always wished were there.

145 lines 20.8 kB
import { Observable } from 'rxjs'; import { Directive, Input } from '@angular/core'; import { OnObserverBaseDirective } from '../abstraction/on-observer-base.directive'; import * as i0 from "@angular/core"; /** * Documentation in {@link OnObserverActiveDirective.onObserverActive} to allow in-template tooltips. * * @export * @class OnObserverActiveDirective * @extends {OnObserverBaseDirective<T>} * @template T The type of value the observable emits. */ export class OnObserverActiveDirective extends OnObserverBaseDirective { constructor() { super(...arguments); this.selector = 'onObserverActive'; this.renderOnCallsTo = ['resolving', 'next']; } /** * Renders the template when the specified observable is either resolving its first value, or emits a value. * * ## Features * * #### View Context * Use the microsyntax `as` keyword to assign resolved values to a variable. * Use the microsyntax `let` keyword to assign the {@link OnObserverContext full context object} to a variable (e.g. `let context`). * * #### Delayed rendering * Specify a value for {@link OnObserverBaseDirective.showAfter `showAfter`} to delay rendering. * * #### Auto destroy * Specify {@link OnObserverBaseDirective.showFor `showFor`} to automatically destroy the view after a certain duration. * * #### Countdown updates * When {@link OnObserverBaseDirective.showFor `showFor`} is specified, the view context will be updated with the time remaining until the view * is destroyed and the time elapsed since it was rendered. This allows giving the user feedback in a progress bar, a spinner, a textual timer * or any other UI component. * * Remaining is provided by the {@link OnObserverContext.remaining `remaining`} property. Elapsed time is provided by the {@link OnObserverContext.elapsed `elapsed`} * property. Access it by assigning a variable using `let`, like so: * `let remaining = remaining` * * #### Multi view mode * Specify {@link OnObserverBaseDirective.viewMode `viewMode = 'multiple'`} to enable rendering a new view for each intercepted call * instead of updating a single rendered view. This allows stacking logs, notification snackbars, or any other aggregation functionality. * Combined with {@link OnObserverBaseDirective.showFor `showFor`}, this is great for disappearing messages/notifications. * * #### View index * In multi-view mode, the context will contain the index of the view, which can be used for calculations and styling. */ set onObserverActive(value) { this.input.next(value); } /** * (Optional) The view mode the directive will operate in: * `'single'` - A single view will be rendered on intercepted calls. If a view has already been rendered when a call is intercepted, * the existing view will be updated with data from the new call. * * `'multiple'` - Every new intercepted call will render a new view with its own context and data encapsulated from the current call. * * Default is `'single'`. */ set onObserverActiveViewMode(viewMode) { this.viewMode = viewMode; } /** * (Optional) The duration for which the directive should wait before rendering the view once an intercepted call is made. * * You can specify a number, which will be treated as milliseconds, or a string with the format of `<number><ms | s | ms>`. * Numbers can be either integers or floats. * For example: * - `3000` - Wait for 3 seconds, then render the view. * - `'10s'` - Wait for 10 seconds, then render the view. * - `'0.5m'` - Wait for 30 seconds, then render the view. * - `'100ms'` - Wait for 100 milliseconds, then render the view. * * Default is `0`, meaning immediately render the view. * * TODO: ADD LINK TO TOUR OR FULL WIKI PAGE * Read more {@link OnObserverBaseDirective About render flow}. **/ set onObserverActiveShowAfter(duration) { this.showAfter = duration; } /** * (Optional) The duration for which the view should be rendered. When the duration passes, the view will be auto destroyed. * * You can specify a number, which will be treated as milliseconds, or a string with the format of `<number><ms | s | ms>`. * Numbers can be either integers or floats. * For example: * - `3000` - The view will be destroyed after 3 seconds. * - `'10s'` - The view will be destroyed after 10 seconds. * - `'0.5m'` - The view will be destroyed after 30 seconds. * - `'100ms'` - The view will be destroyed after 100 milliseconds. * * During the time the view is rendered, the context will be updated with a countdown object to facilitate any UI part used to * indicate countdown to the user. The countdown will be exposed through the {@link OnObserverContext.remaining `remaining`} * property and the elapsed time through {@link OnObserverContext.elapsed `elapsed`} property in the view context and can both * be accessed be declaring a `let` variable (e.g. `let remaining = remaining`). * See {@link OnObserverBaseDirective.countdownInterval `countdownInterval`} for changing the updates interval. * * When unspecified, the view will be destroyed immediately once the observer detects a call different to the intercepted ones. * * TODO: ADD LINK TO TOUR OR FULL WIKI PAGE * Read more {@link OnObserverBaseDirective About render flow}. **/ set onObserverActiveShowFor(duration) { this.showFor = duration; } ; /** * ### Only used when passing a value to {@link OnObserverBaseDirective.showFor `showFor`}. * * (Optional) The interval with which countdown updates should be made to the view's context before it auto destroys. * The lower the value, the more updates will be made to the context, but the more resources your directive will consume. * * You can specify a number, which will be treated as milliseconds, or a string with the format of `<number><ms | s | ms>`. * Numbers can be either integers or floats. * For example: * - `3000` - 3 seconds between each update. * - `'10s'` - 10 seconds between each update. * - `'0.5m'` - 30 seconds between each update. * - `'100ms'` - 100 milliseconds between each update. * * You can also specify `'animationFrames'` so the countdown gets updated each time the browser is working on animations. * * When unspecified, the total duration of the countdown will be divided by {@link DefaultCountdownUpdateCount `DefaultCountdownUpdateCount`} * to get a fixed interval which will make for {@link DefaultCountdownUpdateCount `DefaultCountdownUpdateCount`} countdown updates. */ set onObserverActiveCountdownInterval(duration) { this.countdownInterval = duration; } ; static ngTemplateContextGuard(directive, context) { return true; } } OnObserverActiveDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: OnObserverActiveDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); OnObserverActiveDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: OnObserverActiveDirective, selector: "[onObserverActive]", inputs: { onObserverActive: "onObserverActive", onObserverActiveViewMode: "onObserverActiveViewMode", onObserverActiveShowAfter: "onObserverActiveShowAfter", onObserverActiveShowFor: "onObserverActiveShowFor", onObserverActiveCountdownInterval: "onObserverActiveCountdownInterval" }, usesInheritance: true, ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: OnObserverActiveDirective, decorators: [{ type: Directive, args: [{ // eslint-disable-next-line @angular-eslint/directive-selector selector: '[onObserverActive]' }] }], propDecorators: { onObserverActive: [{ type: Input }], onObserverActiveViewMode: [{ type: Input }], onObserverActiveShowAfter: [{ type: Input }], onObserverActiveShowFor: [{ type: Input }], onObserverActiveCountdownInterval: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib24tb2JzZXJ2ZXItYWN0aXZlLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL2xpYnMvYW5ndWxhci16ZW4vY29yZS9zcmMvcnhqcy9vbi1vYnNlcnZlci9kaXJlY3RpdmVzL29uLW9ic2VydmVyLWFjdGl2ZS5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBUSxNQUFNLE1BQU0sQ0FBQztBQUN4QyxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUlqRCxPQUFPLEVBQUUsdUJBQXVCLEVBQXFCLE1BQU0sMkNBQTJDLENBQUM7O0FBRXZHOzs7Ozs7O0dBT0c7QUFLSCxNQUFNLE9BQU8seUJBQTZCLFNBQVEsdUJBQTBCO0lBSjVFOztRQU1jLGFBQVEsR0FBMEIsa0JBQWtCLENBQUM7UUFDckQsb0JBQWUsR0FBbUIsQ0FBQyxXQUFXLEVBQUUsTUFBTSxDQUFDLENBQUM7S0E0R3JFO0lBMUdHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O09BK0JHO0lBQ0gsSUFBb0IsZ0JBQWdCLENBQUMsS0FBb0IsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFdEY7Ozs7Ozs7O09BUUc7SUFDSCxJQUFvQix3QkFBd0IsQ0FBVSxRQUFrQixJQUFjLElBQUksQ0FBQyxRQUFRLEdBQVksUUFBUSxDQUFDLENBQUMsQ0FBQztJQUMxSDs7Ozs7Ozs7Ozs7Ozs7O1FBZUk7SUFDSixJQUFvQix5QkFBeUIsQ0FBUyxRQUE0QixJQUFJLElBQUksQ0FBQyxTQUFTLEdBQVcsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUMxSDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O1FBcUJJO0lBQ0osSUFBb0IsdUJBQXVCLENBQVcsUUFBNEIsSUFBSSxJQUFJLENBQUMsT0FBTyxHQUFhLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFBQSxDQUFDO0lBQzNIOzs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FrQkc7SUFDSCxJQUFvQixpQ0FBaUMsQ0FBQyxRQUFnRCxJQUFJLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQUEsQ0FBQztJQUUvSSxNQUFNLENBQUMsc0JBQXNCLENBQUksU0FBdUMsRUFBRSxPQUFnQixJQUFxQyxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUM7O3VIQTlHcEkseUJBQXlCOzJHQUF6Qix5QkFBeUI7NEZBQXpCLHlCQUF5QjtrQkFKckMsU0FBUzttQkFBQztvQkFDUCw4REFBOEQ7b0JBQzlELFFBQVEsRUFBRSxvQkFBb0I7aUJBQ2pDOzhCQXNDdUIsZ0JBQWdCO3NCQUFuQyxLQUFLO2dCQVdjLHdCQUF3QjtzQkFBM0MsS0FBSztnQkFpQmMseUJBQXlCO3NCQUE1QyxLQUFLO2dCQXVCYyx1QkFBdUI7c0JBQTFDLEtBQUs7Z0JBb0JjLGlDQUFpQztzQkFBcEQsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9ic2VydmFibGUgICAgICAgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IERpcmVjdGl2ZSwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgRHVyYXRpb25Bbm5vdGF0aW9uLCBPYnNlcnZlck5hbWUsIFZpZXdNb2RlIH0gZnJvbSAnLi4vYWJzdHJhY3Rpb24vdHlwZXMvZ2VuZXJhbCc7XG5pbXBvcnQgeyBPbk9ic2VydmVyQ29udGV4dCAgICAgICAgICAgICAgICAgICAgICAgICAgfSBmcm9tICcuLi9hYnN0cmFjdGlvbi90eXBlcy9vbi1vYnNlcnZlci1jb250ZXh0JztcbmltcG9ydCB7IE9uT2JzZXJ2ZXJCYXNlRGlyZWN0aXZlICAgICAgICAgICAgICAgICAgICB9IGZyb20gJy4uL2Fic3RyYWN0aW9uL29uLW9ic2VydmVyLWJhc2UuZGlyZWN0aXZlJztcblxuLyoqXG4gKiBEb2N1bWVudGF0aW9uIGluIHtAbGluayBPbk9ic2VydmVyQWN0aXZlRGlyZWN0aXZlLm9uT2JzZXJ2ZXJBY3RpdmV9IHRvIGFsbG93IGluLXRlbXBsYXRlIHRvb2x0aXBzLlxuICogXG4gKiBAZXhwb3J0XG4gKiBAY2xhc3MgT25PYnNlcnZlckFjdGl2ZURpcmVjdGl2ZVxuICogQGV4dGVuZHMge09uT2JzZXJ2ZXJCYXNlRGlyZWN0aXZlPFQ+fVxuICogQHRlbXBsYXRlIFQgVGhlIHR5cGUgb2YgdmFsdWUgdGhlIG9ic2VydmFibGUgZW1pdHMuXG4gKi9cbkBEaXJlY3RpdmUoe1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAYW5ndWxhci1lc2xpbnQvZGlyZWN0aXZlLXNlbGVjdG9yXG4gICAgc2VsZWN0b3I6ICdbb25PYnNlcnZlckFjdGl2ZV0nXG59KVxuZXhwb3J0IGNsYXNzIE9uT2JzZXJ2ZXJBY3RpdmVEaXJlY3RpdmU8VD4gZXh0ZW5kcyBPbk9ic2VydmVyQmFzZURpcmVjdGl2ZTxUPlxue1xuICAgIHByb3RlY3RlZCBzZWxlY3RvciAgICAgICAgICAgICAgICAgICAgICAgID0gJ29uT2JzZXJ2ZXJBY3RpdmUnO1xuICAgIHByb3RlY3RlZCByZW5kZXJPbkNhbGxzVG86IE9ic2VydmVyTmFtZVtdID0gWydyZXNvbHZpbmcnLCAnbmV4dCddO1xuICAgIFxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIHRlbXBsYXRlIHdoZW4gdGhlIHNwZWNpZmllZCBvYnNlcnZhYmxlIGlzIGVpdGhlciByZXNvbHZpbmcgaXRzIGZpcnN0IHZhbHVlLCBvciBlbWl0cyBhIHZhbHVlLlxuICAgICAqIFxuICAgICAqICMjIEZlYXR1cmVzXG4gICAgICogXG4gICAgICogIyMjIyBWaWV3IENvbnRleHRcbiAgICAgKiBVc2UgdGhlIG1pY3Jvc3ludGF4IGBhc2Aga2V5d29yZCB0byBhc3NpZ24gcmVzb2x2ZWQgdmFsdWVzIHRvIGEgdmFyaWFibGUuXG4gICAgICogVXNlIHRoZSBtaWNyb3N5bnRheCBgbGV0YCBrZXl3b3JkIHRvIGFzc2lnbiB0aGUge0BsaW5rIE9uT2JzZXJ2ZXJDb250ZXh0IGZ1bGwgY29udGV4dCBvYmplY3R9IHRvIGEgdmFyaWFibGUgKGUuZy4gYGxldCBjb250ZXh0YCkuXG4gICAgICogIFxuICAgICAqICMjIyMgRGVsYXllZCByZW5kZXJpbmdcbiAgICAgKiBTcGVjaWZ5IGEgdmFsdWUgZm9yIHtAbGluayBPbk9ic2VydmVyQmFzZURpcmVjdGl2ZS5zaG93QWZ0ZXIgYHNob3dBZnRlcmB9IHRvIGRlbGF5IHJlbmRlcmluZy5cbiAgICAgKiBcbiAgICAgKiAjIyMjIEF1dG8gZGVzdHJveVxuICAgICAqIFNwZWNpZnkge0BsaW5rIE9uT2JzZXJ2ZXJCYXNlRGlyZWN0aXZlLnNob3dGb3IgYHNob3dGb3JgfSB0byBhdXRvbWF0aWNhbGx5IGRlc3Ryb3kgdGhlIHZpZXcgYWZ0ZXIgYSBjZXJ0YWluIGR1cmF0aW9uLlxuICAgICAqIFxuICAgICAqICMjIyMgQ291bnRkb3duIHVwZGF0ZXNcbiAgICAgKiBXaGVuIHtAbGluayBPbk9ic2VydmVyQmFzZURpcmVjdGl2ZS5zaG93Rm9yIGBzaG93Rm9yYH0gaXMgc3BlY2lmaWVkLCB0aGUgdmlldyBjb250ZXh0IHdpbGwgYmUgdXBkYXRlZCB3aXRoIHRoZSB0aW1lIHJlbWFpbmluZyB1bnRpbCB0aGUgdmlld1xuICAgICAqIGlzIGRlc3Ryb3llZCBhbmQgdGhlIHRpbWUgZWxhcHNlZCBzaW5jZSBpdCB3YXMgcmVuZGVyZWQuIFRoaXMgYWxsb3dzIGdpdmluZyB0aGUgdXNlciBmZWVkYmFjayBpbiBhIHByb2dyZXNzIGJhciwgYSBzcGlubmVyLCBhIHRleHR1YWwgdGltZXJcbiAgICAgKiBvciBhbnkgb3RoZXIgVUkgY29tcG9uZW50LiBcbiAgICAgKiBcbiAgICAgKiBSZW1haW5pbmcgaXMgcHJvdmlkZWQgYnkgdGhlIHtAbGluayBPbk9ic2VydmVyQ29udGV4dC5yZW1haW5pbmcgYHJlbWFpbmluZ2B9IHByb3BlcnR5LiBFbGFwc2VkIHRpbWUgaXMgcHJvdmlkZWQgYnkgdGhlIHtAbGluayBPbk9ic2VydmVyQ29udGV4dC5lbGFwc2VkIGBlbGFwc2VkYH1cbiAgICAgKiBwcm9wZXJ0eS4gQWNjZXNzIGl0IGJ5IGFzc2lnbmluZyBhIHZhcmlhYmxlIHVzaW5nIGBsZXRgLCBsaWtlIHNvOiAgXG4gICAgICogYGxldCByZW1haW5pbmcgPSByZW1haW5pbmdgXG4gICAgICogXG4gICAgICogIyMjIyBNdWx0aSB2aWV3IG1vZGVcbiAgICAgKiBTcGVjaWZ5IHtAbGluayBPbk9ic2VydmVyQmFzZURpcmVjdGl2ZS52aWV3TW9kZSBgdmlld01vZGUgPSAnbXVsdGlwbGUnYH0gdG8gZW5hYmxlIHJlbmRlcmluZyBhIG5ldyB2aWV3IGZvciBlYWNoIGludGVyY2VwdGVkIGNhbGxcbiAgICAgKiBpbnN0ZWFkIG9mIHVwZGF0aW5nIGEgc2luZ2xlIHJlbmRlcmVkIHZpZXcuIFRoaXMgYWxsb3dzIHN0YWNraW5nIGxvZ3MsIG5vdGlmaWNhdGlvbiBzbmFja2JhcnMsIG9yIGFueSBvdGhlciBhZ2dyZWdhdGlvbiBmdW5jdGlvbmFsaXR5LlxuICAgICAqIENvbWJpbmVkIHdpdGgge0BsaW5rIE9uT2JzZXJ2ZXJCYXNlRGlyZWN0aXZlLnNob3dGb3IgYHNob3dGb3JgfSwgdGhpcyBpcyBncmVhdCBmb3IgZGlzYXBwZWFyaW5nIG1lc3NhZ2VzL25vdGlmaWNhdGlvbnMuXG4gICAgICogXG4gICAgICogIyMjIyBWaWV3IGluZGV4XG4gICAgICogSW4gbXVsdGktdmlldyBtb2RlLCB0aGUgY29udGV4dCB3aWxsIGNvbnRhaW4gdGhlIGluZGV4IG9mIHRoZSB2aWV3LCB3aGljaCBjYW4gYmUgdXNlZCBmb3IgY2FsY3VsYXRpb25zIGFuZCBzdHlsaW5nLlxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBzZXQgb25PYnNlcnZlckFjdGl2ZSh2YWx1ZTogT2JzZXJ2YWJsZTxUPikgeyB0aGlzLmlucHV0Lm5leHQodmFsdWUpOyB9XG5cbiAgICAvKipcbiAgICAgKiAoT3B0aW9uYWwpIFRoZSB2aWV3IG1vZGUgdGhlIGRpcmVjdGl2ZSB3aWxsIG9wZXJhdGUgaW46ICBcbiAgICAgKiBgJ3NpbmdsZSdgIC0gQSBzaW5nbGUgdmlldyB3aWxsIGJlIHJlbmRlcmVkIG9uIGludGVyY2VwdGVkIGNhbGxzLiBJZiBhIHZpZXcgaGFzIGFscmVhZHkgYmVlbiByZW5kZXJlZCB3aGVuIGEgY2FsbCBpcyBpbnRlcmNlcHRlZCxcbiAgICAgKiB0aGUgZXhpc3RpbmcgdmlldyB3aWxsIGJlIHVwZGF0ZWQgd2l0aCBkYXRhIGZyb20gdGhlIG5ldyBjYWxsLlxuICAgICAqIFxuICAgICAqIGAnbXVsdGlwbGUnYCAtIEV2ZXJ5IG5ldyBpbnRlcmNlcHRlZCBjYWxsIHdpbGwgcmVuZGVyIGEgbmV3IHZpZXcgd2l0aCBpdHMgb3duIGNvbnRleHQgYW5kIGRhdGEgZW5jYXBzdWxhdGVkIGZyb20gdGhlIGN1cnJlbnQgY2FsbC5cbiAgICAgKiBcbiAgICAgKiBEZWZhdWx0IGlzIGAnc2luZ2xlJ2AuXG4gICAgICovXG4gICAgQElucHV0KCkgcHVibGljIHNldCBvbk9ic2VydmVyQWN0aXZlVmlld01vZGUgICAgICAgICAodmlld01vZGU6IFZpZXdNb2RlICAgICAgICAgICkgeyB0aGlzLnZpZXdNb2RlICAgICAgICAgID0gdmlld01vZGU7IH1cbiAgICAvKipcbiAgICAgKiAoT3B0aW9uYWwpIFRoZSBkdXJhdGlvbiBmb3Igd2hpY2ggdGhlIGRpcmVjdGl2ZSBzaG91bGQgd2FpdCBiZWZvcmUgcmVuZGVyaW5nIHRoZSB2aWV3IG9uY2UgYW4gaW50ZXJjZXB0ZWQgY2FsbCBpcyBtYWRlLlxuICAgICAqIFxuICAgICAqIFlvdSBjYW4gc3BlY2lmeSBhIG51bWJlciwgd2hpY2ggd2lsbCBiZSB0cmVhdGVkIGFzIG1pbGxpc2Vjb25kcywgb3IgYSBzdHJpbmcgd2l0aCB0aGUgZm9ybWF0IG9mIGA8bnVtYmVyPjxtcyB8IHMgfCBtcz5gLlxuICAgICAqIE51bWJlcnMgY2FuIGJlIGVpdGhlciBpbnRlZ2VycyBvciBmbG9hdHMuXG4gICAgICogRm9yIGV4YW1wbGU6XG4gICAgICogLSBgMzAwMGAgLSBXYWl0IGZvciAzIHNlY29uZHMsIHRoZW4gcmVuZGVyIHRoZSB2aWV3LlxuICAgICAqIC0gYCcxMHMnYCAtIFdhaXQgZm9yIDEwIHNlY29uZHMsIHRoZW4gcmVuZGVyIHRoZSB2aWV3LlxuICAgICAqIC0gYCcwLjVtJ2AgLSBXYWl0IGZvciAzMCBzZWNvbmRzLCB0aGVuIHJlbmRlciB0aGUgdmlldy5cbiAgICAgKiAtIGAnMTAwbXMnYCAtIFdhaXQgZm9yIDEwMCBtaWxsaXNlY29uZHMsIHRoZW4gcmVuZGVyIHRoZSB2aWV3LlxuICAgICAqIFxuICAgICAqIERlZmF1bHQgaXMgYDBgLCBtZWFuaW5nIGltbWVkaWF0ZWx5IHJlbmRlciB0aGUgdmlldy5cbiAgICAgKlxuICAgICAqIFRPRE86IEFERCBMSU5LIFRPIFRPVVIgT1IgRlVMTCBXSUtJIFBBR0VcbiAgICAgKiBSZWFkIG1vcmUge0BsaW5rIE9uT2JzZXJ2ZXJCYXNlRGlyZWN0aXZlIEFib3V0IHJlbmRlciBmbG93fS5cbiAgICAgKiovXG4gICAgQElucHV0KCkgcHVibGljIHNldCBvbk9ic2VydmVyQWN0aXZlU2hvd0FmdGVyICAgICAgICAoZHVyYXRpb246IER1cmF0aW9uQW5ub3RhdGlvbikgeyB0aGlzLnNob3dBZnRlciAgICAgICAgID0gZHVyYXRpb247IH1cbiAgICAvKipcbiAgICAgKiAoT3B0aW9uYWwpIFRoZSBkdXJhdGlvbiBmb3Igd2hpY2ggdGhlIHZpZXcgc2hvdWxkIGJlIHJlbmRlcmVkLiBXaGVuIHRoZSBkdXJhdGlvbiBwYXNzZXMsIHRoZSB2aWV3IHdpbGwgYmUgYXV0byBkZXN0cm95ZWQuXG4gICAgICpcbiAgICAgKiBZb3UgY2FuIHNwZWNpZnkgYSBudW1iZXIsIHdoaWNoIHdpbGwgYmUgdHJlYXRlZCBhcyBtaWxsaXNlY29uZHMsIG9yIGEgc3RyaW5nIHdpdGggdGhlIGZvcm1hdCBvZiBgPG51bWJlcj48bXMgfCBzIHwgbXM+YC5cbiAgICAgKiBOdW1iZXJzIGNhbiBiZSBlaXRoZXIgaW50ZWdlcnMgb3IgZmxvYXRzLlxuICAgICAqIEZvciBleGFtcGxlOlxuICAgICAqIC0gYDMwMDBgIC0gVGhlIHZpZXcgd2lsbCBiZSBkZXN0cm95ZWQgYWZ0ZXIgMyBzZWNvbmRzLlxuICAgICAqIC0gYCcxMHMnYCAtIFRoZSB2aWV3IHdpbGwgYmUgZGVzdHJveWVkIGFmdGVyIDEwIHNlY29uZHMuXG4gICAgICogLSBgJzAuNW0nYCAtIFRoZSB2aWV3IHdpbGwgYmUgZGVzdHJveWVkIGFmdGVyIDMwIHNlY29uZHMuXG4gICAgICogLSBgJzEwMG1zJ2AgLSBUaGUgdmlldyB3aWxsIGJlIGRlc3Ryb3llZCBhZnRlciAxMDAgbWlsbGlzZWNvbmRzLlxuICAgICAqIFxuICAgICAqIER1cmluZyB0aGUgdGltZSB0aGUgdmlldyBpcyByZW5kZXJlZCwgdGhlIGNvbnRleHQgd2lsbCBiZSB1cGRhdGVkIHdpdGggYSBjb3VudGRvd24gb2JqZWN0IHRvIGZhY2lsaXRhdGUgYW55IFVJIHBhcnQgdXNlZCB0b1xuICAgICAqIGluZGljYXRlIGNvdW50ZG93biB0byB0aGUgdXNlci4gVGhlIGNvdW50ZG93biB3aWxsIGJlIGV4cG9zZWQgdGhyb3VnaCB0aGUge0BsaW5rIE9uT2JzZXJ2ZXJDb250ZXh0LnJlbWFpbmluZyBgcmVtYWluaW5nYH1cbiAgICAgKiBwcm9wZXJ0eSBhbmQgdGhlIGVsYXBzZWQgdGltZSB0aHJvdWdoIHtAbGluayBPbk9ic2VydmVyQ29udGV4dC5lbGFwc2VkIGBlbGFwc2VkYH0gcHJvcGVydHkgaW4gdGhlIHZpZXcgY29udGV4dCBhbmQgY2FuIGJvdGhcbiAgICAgKiBiZSBhY2Nlc3NlZCBiZSBkZWNsYXJpbmcgYSBgbGV0YCB2YXJpYWJsZSAoZS5nLiBgbGV0IHJlbWFpbmluZyA9IHJlbWFpbmluZ2ApLlxuICAgICAqIFNlZSB7QGxpbmsgT25PYnNlcnZlckJhc2VEaXJlY3RpdmUuY291bnRkb3duSW50ZXJ2YWwgYGNvdW50ZG93bkludGVydmFsYH0gZm9yIGNoYW5naW5nIHRoZSB1cGRhdGVzIGludGVydmFsLlxuICAgICAqIFxuICAgICAqIFdoZW4gdW5zcGVjaWZpZWQsIHRoZSB2aWV3IHdpbGwgYmUgZGVzdHJveWVkIGltbWVkaWF0ZWx5IG9uY2UgdGhlIG9ic2VydmVyIGRldGVjdHMgYSBjYWxsIGRpZmZlcmVudCB0byB0aGUgaW50ZXJjZXB0ZWQgb25lcy5cbiAgICAgKiBcbiAgICAgKiBUT0RPOiBBREQgTElOSyBUTyBUT1VSIE9SIEZVTEwgV0lLSSBQQUdFXG4gICAgICogUmVhZCBtb3JlIHtAbGluayBPbk9ic2VydmVyQmFzZURpcmVjdGl2ZSBBYm91dCByZW5kZXIgZmxvd30uXG4gICAgICoqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBzZXQgb25PYnNlcnZlckFjdGl2ZVNob3dGb3IgICAgICAgICAgKGR1cmF0aW9uOiBEdXJhdGlvbkFubm90YXRpb24pIHsgdGhpcy5zaG93Rm9yICAgICAgICAgICA9IGR1cmF0aW9uOyB9O1xuICAgIC8qKlxuICAgICAqICMjIyBPbmx5IHVzZWQgd2hlbiBwYXNzaW5nIGEgdmFsdWUgdG8ge0BsaW5rIE9uT2JzZXJ2ZXJCYXNlRGlyZWN0aXZlLnNob3dGb3IgYHNob3dGb3JgfS5cbiAgICAgKiBcbiAgICAgKiAoT3B0aW9uYWwpIFRoZSBpbnRlcnZhbCB3aXRoIHdoaWNoIGNvdW50ZG93biB1cGRhdGVzIHNob3VsZCBiZSBtYWRlIHRvIHRoZSB2aWV3J3MgY29udGV4dCBiZWZvcmUgaXQgYXV0byBkZXN0cm95cy5cbiAgICAgKiBUaGUgbG93ZXIgdGhlIHZhbHVlLCB0aGUgbW9yZSB1cGRhdGVzIHdpbGwgYmUgbWFkZSB0byB0aGUgY29udGV4dCwgYnV0IHRoZSBtb3JlIHJlc291cmNlcyB5b3VyIGRpcmVjdGl2ZSB3aWxsIGNvbnN1bWUuXG4gICAgICogXG4gICAgICogWW91IGNhbiBzcGVjaWZ5IGEgbnVtYmVyLCB3aGljaCB3aWxsIGJlIHRyZWF0ZWQgYXMgbWlsbGlzZWNvbmRzLCBvciBhIHN0cmluZyB3aXRoIHRoZSBmb3JtYXQgb2YgYDxudW1iZXI+PG1zIHwgcyB8IG1zPmAuXG4gICAgICogTnVtYmVycyBjYW4gYmUgZWl0aGVyIGludGVnZXJzIG9yIGZsb2F0cy5cbiAgICAgKiBGb3IgZXhhbXBsZTpcbiAgICAgKiAtIGAzMDAwYCAtIDMgc2Vjb25kcyBiZXR3ZWVuIGVhY2ggdXBkYXRlLlxuICAgICAqIC0gYCcxMHMnYCAtIDEwIHNlY29uZHMgYmV0d2VlbiBlYWNoIHVwZGF0ZS5cbiAgICAgKiAtIGAnMC41bSdgIC0gMzAgc2Vjb25kcyBiZXR3ZWVuIGVhY2ggdXBkYXRlLlxuICAgICAqIC0gYCcxMDBtcydgIC0gMTAwIG1pbGxpc2Vjb25kcyBiZXR3ZWVuIGVhY2ggdXBkYXRlLlxuICAgICAqIFxuICAgICAqIFlvdSBjYW4gYWxzbyBzcGVjaWZ5IGAnYW5pbWF0aW9uRnJhbWVzJ2Agc28gdGhlIGNvdW50ZG93biBnZXRzIHVwZGF0ZWQgZWFjaCB0aW1lIHRoZSBicm93c2VyIGlzIHdvcmtpbmcgb24gYW5pbWF0aW9ucy5cbiAgICAgKiBcbiAgICAgKiBXaGVuIHVuc3BlY2lmaWVkLCB0aGUgdG90YWwgZHVyYXRpb24gb2YgdGhlIGNvdW50ZG93biB3aWxsIGJlIGRpdmlkZWQgYnkge0BsaW5rIERlZmF1bHRDb3VudGRvd25VcGRhdGVDb3VudCBgRGVmYXVsdENvdW50ZG93blVwZGF0ZUNvdW50YH1cbiAgICAgKiB0byBnZXQgYSBmaXhlZCBpbnRlcnZhbCB3aGljaCB3aWxsIG1ha2UgZm9yIHtAbGluayBEZWZhdWx0Q291bnRkb3duVXBkYXRlQ291bnQgYERlZmF1bHRDb3VudGRvd25VcGRhdGVDb3VudGB9IGNvdW50ZG93biB1cGRhdGVzLlxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBzZXQgb25PYnNlcnZlckFjdGl2ZUNvdW50ZG93bkludGVydmFsKGR1cmF0aW9uOiBEdXJhdGlvbkFubm90YXRpb24gfCAnYW5pbWF0aW9uRnJhbWVzJykgeyB0aGlzLmNvdW50ZG93bkludGVydmFsID0gZHVyYXRpb247IH07XG5cbiAgICBzdGF0aWMgbmdUZW1wbGF0ZUNvbnRleHRHdWFyZDxUPihkaXJlY3RpdmU6IE9uT2JzZXJ2ZXJBY3RpdmVEaXJlY3RpdmU8VD4sIGNvbnRleHQ6IHVua25vd24pOiBjb250ZXh0IGlzIE9uT2JzZXJ2ZXJDb250ZXh0PFQ+IHsgcmV0dXJuIHRydWU7IH1cbn0iXX0=