Remove unused blade settings pages not linked from UI Convert remaining frontend pages to SPA actions Convert settings user_settings and general to SPA actions Convert settings profile pages to SPA actions Convert contacts and projects add/edit pages to SPA actions Convert clients add/edit page to SPA action with loading pattern Refactor component scoped IDs from $id to $sid Fix jqhtml comment syntax and implement universal error component system Update all application code to use new unified error system Remove all backwards compatibility - unified error system complete Phase 5: Remove old response classes Phase 3-4: Ajax response handler sends new format, old helpers deprecated Phase 2: Add client-side unified error foundation Phase 1: Add server-side unified error foundation Add unified Ajax error response system with constants 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
343 lines
40 KiB
JavaScript
Executable File
343 lines
40 KiB
JavaScript
Executable File
"use strict";
|
|
|
|
/**
|
|
* Rsx_Modal Component
|
|
*
|
|
* Instance of a modal dialog. Handles lifecycle, sizing, and user interaction.
|
|
* Typically created and managed by the Modal static API class.
|
|
*/
|
|
class Rsx_Modal extends Component {
|
|
on_create() {
|
|
this.data.title = '';
|
|
this.data.body_content = null;
|
|
this.data.buttons = [];
|
|
this.data.closable = true;
|
|
this.data.max_width = 800;
|
|
this.data.close_on_submit = true;
|
|
this.data.is_visible = false;
|
|
this.data.result_promise = null;
|
|
this.data.resolve_fn = null;
|
|
|
|
// Store reference to bootstrap modal instance
|
|
this._bs_modal = null;
|
|
this._resize_handler = null;
|
|
}
|
|
on_ready() {
|
|
const that = this;
|
|
|
|
// Set up close button handler
|
|
this.$sid('close_btn').on('click', function (e) {
|
|
e.preventDefault();
|
|
if (that.data.closable) {
|
|
that.close(false);
|
|
}
|
|
});
|
|
|
|
// Set up backdrop click handler
|
|
this.$sid('backdrop').on('click', function (e) {
|
|
if (that.data.closable && e.target === this) {
|
|
that.close(false);
|
|
}
|
|
});
|
|
|
|
// Set up ESC key handler
|
|
$(document).on('keydown.rsx_modal_' + this._cid, function (e) {
|
|
if (e.key === 'Escape' && that.data.closable && that.data.is_visible) {
|
|
that.close(false);
|
|
}
|
|
});
|
|
|
|
// Set up resize handler
|
|
this._resize_handler = debounce(() => {
|
|
if (that.data.is_visible) {
|
|
that._apply_sizing();
|
|
}
|
|
}, 100);
|
|
$(window).on('resize.rsx_modal_' + this._cid, this._resize_handler);
|
|
}
|
|
|
|
/**
|
|
* Configure and show the modal
|
|
* @param {Object} options - Modal options (title, body, buttons, etc.)
|
|
* @param {Object} internal_options - Internal options (skip_backdrop, animate)
|
|
*/
|
|
async show(options) {
|
|
let internal_options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
const that = this;
|
|
const skip_backdrop = internal_options.skip_backdrop || false;
|
|
const should_animate = internal_options.animate || false;
|
|
console.log('[Rsx_Modal] show() called with options:', options);
|
|
|
|
// Store options
|
|
this.data.title = options.title || '';
|
|
this.data.closable = options.closable !== undefined ? options.closable : true;
|
|
this.data.max_width = options.max_width || 800;
|
|
this.data.close_on_submit = options.close_on_submit !== undefined ? options.close_on_submit : true;
|
|
this.data.buttons = options.buttons || [];
|
|
this.data.skip_backdrop = skip_backdrop;
|
|
this.data.icon = options.icon || null;
|
|
console.log('[Rsx_Modal] Setting title to:', this.data.title);
|
|
console.log('[Rsx_Modal] Title element:', this.$sid('title'));
|
|
|
|
// Set title
|
|
this.$sid('title').text(this.data.title);
|
|
|
|
// Show/hide close button based on closable
|
|
if (this.data.closable) {
|
|
this.$sid('close_btn').show();
|
|
} else {
|
|
this.$sid('close_btn').hide();
|
|
}
|
|
|
|
// Set body content (with optional icon)
|
|
this._set_body_content(options.body, this.data.icon);
|
|
|
|
// Set buttons
|
|
this._set_buttons();
|
|
|
|
// Create promise that will resolve when modal closes
|
|
const result_promise = new Promise(resolve => {
|
|
that.data.resolve_fn = resolve;
|
|
});
|
|
|
|
// Show modal and backdrop
|
|
this.data.is_visible = true;
|
|
|
|
// Append to body so it's on top (don't append backdrop if using shared)
|
|
if (!skip_backdrop) {
|
|
$('body').append(this.$sid('backdrop'));
|
|
}
|
|
$('body').append(this.$);
|
|
|
|
// Apply sizing before showing
|
|
this._apply_sizing();
|
|
|
|
// Fade in modal (and backdrop if not using shared)
|
|
await this._fade_in(should_animate);
|
|
|
|
// Auto-focus first input element
|
|
this._focus_first_input();
|
|
return result_promise;
|
|
}
|
|
|
|
/**
|
|
* Set body content with optional icon
|
|
*/
|
|
_set_body_content(body, icon) {
|
|
const $body = this.$sid('body');
|
|
$body.empty();
|
|
|
|
// If icon provided, add it
|
|
if (icon) {
|
|
const $icon = $(`<i class="bi bi-${icon} modal-icon"></i>`);
|
|
$body.append($icon);
|
|
$body.addClass('has-icon');
|
|
} else {
|
|
$body.removeClass('has-icon');
|
|
}
|
|
|
|
// Get or create body content wrapper
|
|
let $content = this.$sid('body_content');
|
|
if (!$content.exists()) {
|
|
$content = $('<div class="modal-body-content"></div>');
|
|
$body.append($content);
|
|
}
|
|
if (typeof body === 'string') {
|
|
// Text content - escape and convert newlines
|
|
const escaped = $('<div>').text(body).html().replace(/\n/g, '<br>');
|
|
$content.html(escaped);
|
|
} else if (body instanceof jQuery) {
|
|
// jQuery element
|
|
$content.append(body);
|
|
} else if (body && typeof body === 'object') {
|
|
// Assume it's a jqhtml component instance
|
|
$content.append(body.$);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set buttons in footer
|
|
*/
|
|
_set_buttons() {
|
|
const that = this;
|
|
const $footer = this.$sid('footer');
|
|
$footer.empty();
|
|
if (this.data.buttons.length === 0) {
|
|
$footer.hide();
|
|
return;
|
|
}
|
|
$footer.show();
|
|
for (let button_def of this.data.buttons) {
|
|
const $button = $('<button>').attr('type', 'button').addClass('btn').addClass(button_def.class || 'btn-secondary').text(button_def.label || 'Button');
|
|
$button.on('click', async function () {
|
|
let result = button_def.value;
|
|
let had_callback = false;
|
|
|
|
// If button has a callback, call it and use return value as result
|
|
if (button_def.callback && typeof button_def.callback === 'function') {
|
|
had_callback = true;
|
|
result = await button_def.callback();
|
|
}
|
|
|
|
// If callback returned false, keep modal open (but not if just button value is false)
|
|
if (result === false && had_callback) {
|
|
return;
|
|
}
|
|
|
|
// Close modal with result
|
|
that.close(result);
|
|
});
|
|
$footer.append($button);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calculate and apply responsive sizing
|
|
*/
|
|
_apply_sizing() {
|
|
const viewport_width = $(window).width();
|
|
const viewport_height = $(window).height();
|
|
const is_mobile = viewport_width < 768;
|
|
|
|
// Calculate max width based on viewport
|
|
let max_width = this.data.max_width;
|
|
const viewport_limit = is_mobile ? viewport_width * 0.9 : viewport_width * 0.8;
|
|
max_width = Math.min(max_width, viewport_limit);
|
|
|
|
// Try to constrain to 60% width for better proportions on desktop
|
|
if (!is_mobile) {
|
|
const preferred_width = viewport_width * 0.6;
|
|
if (preferred_width < max_width) {
|
|
max_width = preferred_width;
|
|
}
|
|
}
|
|
|
|
// Apply width
|
|
this.$sid('dialog').css('max-width', max_width + 'px');
|
|
|
|
// Check if content exceeds 80% height
|
|
const content_height = this.$sid('dialog').outerHeight();
|
|
const max_height = viewport_height * 0.8;
|
|
if (content_height > max_height) {
|
|
// Enable scrolling
|
|
this.$sid('dialog').css('max-height', max_height + 'px');
|
|
this.$sid('body').css({
|
|
'overflow-y': 'auto',
|
|
'max-height': max_height - 150 + 'px' // Account for header/footer
|
|
});
|
|
} else {
|
|
// Reset scrolling
|
|
this.$sid('dialog').css('max-height', '');
|
|
this.$sid('body').css({
|
|
'overflow-y': '',
|
|
'max-height': ''
|
|
});
|
|
}
|
|
|
|
// Mobile edge spacing
|
|
if (is_mobile) {
|
|
this.$sid('dialog').css('margin', '5%');
|
|
} else {
|
|
this.$sid('dialog').css('margin', '0');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Show animation (instant or with fly-in)
|
|
* @param {boolean} animate - Whether to animate the modal entrance
|
|
*/
|
|
async _fade_in() {
|
|
let animate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
if (animate) {
|
|
// Initial state: modal positioned above final position
|
|
this.$.css('display', 'flex').css('opacity', '0');
|
|
this.$sid('modal').css({
|
|
'transform': 'translate(0, -50px)',
|
|
'opacity': '0'
|
|
});
|
|
this.$sid('backdrop').css('display', 'block').addClass('show');
|
|
|
|
// Force reflow
|
|
this.$sid('modal')[0].offsetHeight;
|
|
|
|
// Trigger animation
|
|
this.$sid('modal').addClass('show').css({
|
|
'transform': 'translate(0, 0)',
|
|
'opacity': '1'
|
|
});
|
|
this.$.css('opacity', '1');
|
|
|
|
// Wait for animation to complete
|
|
await new Promise(resolve => setTimeout(resolve, 150));
|
|
} else {
|
|
// Disable transitions temporarily for instant display
|
|
this.$sid('dialog').css('transition', 'none');
|
|
|
|
// Show modal and backdrop instantly
|
|
this.$.css('display', 'flex').css('opacity', '1');
|
|
this.$sid('modal').addClass('show').css('opacity', '1');
|
|
this.$sid('backdrop').css('display', 'block').addClass('show');
|
|
|
|
// Force reflow to apply the no-transition state
|
|
this.$sid('dialog')[0].offsetHeight;
|
|
|
|
// Re-enable transitions for future animations
|
|
this.$sid('dialog').css('transition', '');
|
|
}
|
|
return Promise.resolve();
|
|
}
|
|
|
|
/**
|
|
* Focus the first input element in the modal
|
|
*/
|
|
_focus_first_input() {
|
|
// Find first input/textarea/select in modal body
|
|
const $first_input = this.$sid('body').find('input:not([type="hidden"]), textarea, select').first();
|
|
if ($first_input.exists()) {
|
|
requestAnimationFrame(() => {
|
|
$first_input.focus();
|
|
// Select text if it's an input with existing value
|
|
if ($first_input.is('input[type="text"], input[type="email"]') && $first_input.val()) {
|
|
$first_input.select();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Close the modal instantly
|
|
*/
|
|
async close(result) {
|
|
const that = this;
|
|
|
|
// Mark as not visible
|
|
this.data.is_visible = false;
|
|
|
|
// Remove event listeners
|
|
$(document).off('keydown.rsx_modal_' + this._cid);
|
|
$(window).off('resize.rsx_modal_' + this._cid);
|
|
|
|
// Hide instantly (no fade out)
|
|
this.$.hide();
|
|
this.$sid('backdrop').hide();
|
|
|
|
// Remove from DOM
|
|
this.$.remove();
|
|
this.$sid('backdrop').remove();
|
|
|
|
// Resolve promise
|
|
if (this.data.resolve_fn) {
|
|
this.data.resolve_fn(result);
|
|
this.data.resolve_fn = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Apply validation errors to form fields in modal body
|
|
*/
|
|
apply_errors(errors) {
|
|
// Use Form_Utils to apply errors to elements within modal body
|
|
Form_Utils.apply_form_errors(this.$sid('body'), errors);
|
|
}
|
|
}
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSc3hfTW9kYWwiLCJKcWh0bWxfQ29tcG9uZW50Iiwib25fY3JlYXRlIiwiZGF0YSIsInRpdGxlIiwiYm9keV9jb250ZW50IiwiYnV0dG9ucyIsImNsb3NhYmxlIiwibWF4X3dpZHRoIiwiY2xvc2Vfb25fc3VibWl0IiwiaXNfdmlzaWJsZSIsInJlc3VsdF9wcm9taXNlIiwicmVzb2x2ZV9mbiIsIl9ic19tb2RhbCIsIl9yZXNpemVfaGFuZGxlciIsIm9uX3JlYWR5IiwidGhhdCIsIiRpZCIsIm9uIiwiZSIsInByZXZlbnREZWZhdWx0IiwiY2xvc2UiLCJ0YXJnZXQiLCIkIiwiZG9jdW1lbnQiLCJfY2lkIiwia2V5IiwiZGVib3VuY2UiLCJfYXBwbHlfc2l6aW5nIiwid2luZG93Iiwic2hvdyIsIm9wdGlvbnMiLCJpbnRlcm5hbF9vcHRpb25zIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwidW5kZWZpbmVkIiwic2tpcF9iYWNrZHJvcCIsInNob3VsZF9hbmltYXRlIiwiYW5pbWF0ZSIsImNvbnNvbGUiLCJsb2ciLCJpY29uIiwidGV4dCIsImhpZGUiLCJfc2V0X2JvZHlfY29udGVudCIsImJvZHkiLCJfc2V0X2J1dHRvbnMiLCJQcm9taXNlIiwicmVzb2x2ZSIsImFwcGVuZCIsIl9mYWRlX2luIiwiX2ZvY3VzX2ZpcnN0X2lucHV0IiwiJGJvZHkiLCJlbXB0eSIsIiRpY29uIiwiYWRkQ2xhc3MiLCJyZW1vdmVDbGFzcyIsIiRjb250ZW50IiwiZXhpc3RzIiwiZXNjYXBlZCIsImh0bWwiLCJyZXBsYWNlIiwialF1ZXJ5IiwiJGZvb3RlciIsImJ1dHRvbl9kZWYiLCIkYnV0dG9uIiwiYXR0ciIsImNsYXNzIiwibGFiZWwiLCJyZXN1bHQiLCJ2YWx1ZSIsImhhZF9jYWxsYmFjayIsImNhbGxiYWNrIiwidmlld3BvcnRfd2lkdGgiLCJ3aWR0aCIsInZpZXdwb3J0X2hlaWdodCIsImhlaWdodCIsImlzX21vYmlsZSIsInZpZXdwb3J0X2xpbWl0IiwiTWF0aCIsIm1pbiIsInByZWZlcnJlZF93aWR0aCIsImNzcyIsImNvbnRlbnRfaGVpZ2h0Iiwib3V0ZXJIZWlnaHQiLCJtYXhfaGVpZ2h0Iiwib2Zmc2V0SGVpZ2h0Iiwic2V0VGltZW91dCIsIiRmaXJzdF9pbnB1dCIsImZpbmQiLCJmaXJzdCIsInJlcXVlc3RBbmltYXRpb25GcmFtZSIsImZvY3VzIiwiaXMiLCJ2YWwiLCJzZWxlY3QiLCJvZmYiLCJyZW1vdmUiLCJhcHBseV9lcnJvcnMiLCJlcnJvcnMiLCJGb3JtX1V0aWxzIiwiYXBwbHlfZm9ybV9lcnJvcnMiXSwic291cmNlcyI6WyJyc3gvdGhlbWUvY29tcG9uZW50cy9tb2RhbC9yc3hfbW9kYWwuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBSc3hfTW9kYWwgQ29tcG9uZW50XG4gKlxuICogSW5zdGFuY2Ugb2YgYSBtb2RhbCBkaWFsb2cuIEhhbmRsZXMgbGlmZWN5Y2xlLCBzaXppbmcsIGFuZCB1c2VyIGludGVyYWN0aW9uLlxuICogVHlwaWNhbGx5IGNyZWF0ZWQgYW5kIG1hbmFnZWQgYnkgdGhlIE1vZGFsIHN0YXRpYyBBUEkgY2xhc3MuXG4gKi9cbmNsYXNzIFJzeF9Nb2RhbCBleHRlbmRzIEpxaHRtbF9Db21wb25lbnQge1xuICAgIG9uX2NyZWF0ZSgpIHtcbiAgICAgICAgdGhpcy5kYXRhLnRpdGxlID0gJyc7XG4gICAgICAgIHRoaXMuZGF0YS5ib2R5X2NvbnRlbnQgPSBudWxsO1xuICAgICAgICB0aGlzLmRhdGEuYnV0dG9ucyA9IFtdO1xuICAgICAgICB0aGlzLmRhdGEuY2xvc2FibGUgPSB0cnVlO1xuICAgICAgICB0aGlzLmRhdGEubWF4X3dpZHRoID0gODAwO1xuICAgICAgICB0aGlzLmRhdGEuY2xvc2Vfb25fc3VibWl0ID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5kYXRhLmlzX3Zpc2libGUgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5kYXRhLnJlc3VsdF9wcm9taXNlID0gbnVsbDtcbiAgICAgICAgdGhpcy5kYXRhLnJlc29sdmVfZm4gPSBudWxsO1xuXG4gICAgICAgIC8vIFN0b3JlIHJlZmVyZW5jZSB0byBib290c3RyYXAgbW9kYWwgaW5zdGFuY2VcbiAgICAgICAgdGhpcy5fYnNfbW9kYWwgPSBudWxsO1xuICAgICAgICB0aGlzLl9yZXNpemVfaGFuZGxlciA9IG51bGw7XG4gICAgfVxuXG4gICAgb25fcmVhZHkoKSB7XG4gICAgICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuXG4gICAgICAgIC8vIFNldCB1cCBjbG9zZSBidXR0b24gaGFuZGxlclxuICAgICAgICB0aGlzLiRpZCgnY2xvc2VfYnRuJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIGlmICh0aGF0LmRhdGEuY2xvc2FibGUpIHtcbiAgICAgICAgICAgICAgICB0aGF0LmNsb3NlKGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gU2V0IHVwIGJhY2tkcm9wIGNsaWNrIGhhbmRsZXJcbiAgICAgICAgdGhpcy4kaWQoJ2JhY2tkcm9wJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGlmICh0aGF0LmRhdGEuY2xvc2FibGUgJiYgZS50YXJnZXQgPT09IHRoaXMpIHtcbiAgICAgICAgICAgICAgICB0aGF0LmNsb3NlKGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gU2V0IHVwIEVTQyBrZXkgaGFuZGxlclxuICAgICAgICAkKGRvY3VtZW50KS5vbigna2V5ZG93bi5yc3hfbW9kYWxfJyArIHRoaXMuX2NpZCwgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGlmIChlLmtleSA9PT0gJ0VzY2FwZScgJiYgdGhhdC5kYXRhLmNsb3NhYmxlICYmIHRoYXQuZGF0YS5pc192aXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgdGhhdC5jbG9zZShmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFNldCB1cCByZXNpemUgaGFuZGxlclxuICAgICAgICB0aGlzLl9yZXNpemVfaGFuZGxlciA9IGRlYm91bmNlKCgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGF0LmRhdGEuaXNfdmlzaWJsZSkge1xuICAgICAgICAgICAgICAgIHRoYXQuX2FwcGx5X3NpemluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCAxMDApO1xuXG4gICAgICAgICQod2luZG93KS5vbigncmVzaXplLnJzeF9tb2RhbF8nICsgdGhpcy5fY2lkLCB0aGlzLl9yZXNpemVfaGFuZGxlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29uZmlndXJlIGFuZCBzaG93IHRoZSBtb2RhbFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gTW9kYWwgb3B0aW9ucyAodGl0bGUsIGJvZHksIGJ1dHRvbnMsIGV0Yy4pXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGludGVybmFsX29wdGlvbnMgLSBJbnRlcm5hbCBvcHRpb25zIChza2lwX2JhY2tkcm9wLCBhbmltYXRlKVxuICAgICAqL1xuICAgIGFzeW5jIHNob3cob3B0aW9ucywgaW50ZXJuYWxfb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgICAgICBjb25zdCBza2lwX2JhY2tkcm9wID0gaW50ZXJuYWxfb3B0aW9ucy5za2lwX2JhY2tkcm9wIHx8IGZhbHNlO1xuICAgICAgICBjb25zdCBzaG91bGRfYW5pbWF0ZSA9IGludGVybmFsX29wdGlvbnMuYW5pbWF0ZSB8fCBmYWxzZTtcblxuICAgICAgICBjb25zb2xlLmxvZygnW1JzeF9Nb2RhbF0gc2hvdygpIGNhbGxlZCB3aXRoIG9wdGlvbnM6Jywgb3B0aW9ucyk7XG5cbiAgICAgICAgLy8gU3RvcmUgb3B0aW9uc1xuICAgICAgICB0aGlzLmRhdGEudGl0bGUgPSBvcHRpb25zLnRpdGxlIHx8ICcnO1xuICAgICAgICB0aGlzLmRhdGEuY2xvc2FibGUgPSBvcHRpb25zLmNsb3NhYmxlICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNsb3NhYmxlIDogdHJ1ZTtcbiAgICAgICAgdGhpcy5kYXRhLm1heF93aWR0aCA9IG9wdGlvbnMubWF4X3dpZHRoIHx8IDgwMDtcbiAgICAgICAgdGhpcy5kYXRhLmNsb3NlX29uX3N1Ym1pdCA9IG9wdGlvbnMuY2xvc2Vfb25fc3VibWl0ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNsb3NlX29uX3N1Ym1pdCA6IHRydWU7XG4gICAgICAgIHRoaXMuZGF0YS5idXR0b25zID0gb3B0aW9ucy5idXR0b25zIHx8IFtdO1xuICAgICAgICB0aGlzLmRhdGEuc2tpcF9iYWNrZHJvcCA9IHNraXBfYmFja2Ryb3A7XG4gICAgICAgIHRoaXMuZGF0YS5pY29uID0gb3B0aW9ucy5pY29uIHx8IG51bGw7XG5cbiAgICAgICAgY29uc29sZS5sb2coJ1tSc3hfTW9kYWxdIFNldHRpbmcgdGl0bGUgdG86JywgdGhpcy5kYXRhLnRpdGxlKTtcbiAgICAgICAgY29uc29sZS5sb2coJ1tSc3hfTW9kYWxdIFRpdGxlIGVsZW1lbnQ6JywgdGhpcy4kaWQoJ3RpdGxlJykpO1xuXG4gICAgICAgIC8vIFNldCB0aXRsZVxuICAgICAgICB0aGlzLiRpZCgndGl0bGUnKS50ZXh0KHRoaXMuZGF0YS50aXRsZSk7XG5cbiAgICAgICAgLy8gU2hvdy9oaWRlIGNsb3NlIGJ1dHRvbiBiYXNlZCBvbiBjbG9zYWJsZVxuICAgICAgICBpZiAodGhpcy5kYXRhLmNsb3NhYmxlKSB7XG4gICAgICAgICAgICB0aGlzLiRpZCgnY2xvc2VfYnRuJykuc2hvdygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy4kaWQoJ2Nsb3NlX2J0bicpLmhpZGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCBib2R5IGNvbnRlbnQgKHdpdGggb3B0aW9uYWwgaWNvbilcbiAgICAgICAgdGhpcy5fc2V0X2JvZHlfY29udGVudChvcHRpb25zLmJvZHksIHRoaXMuZGF0YS5pY29uKTtcblxuICAgICAgICAvLyBTZXQgYnV0dG9uc1xuICAgICAgICB0aGlzLl9zZXRfYnV0dG9ucygpO1xuXG4gICAgICAgIC8vIENyZWF0ZSBwcm9taXNlIHRoYXQgd2lsbCByZXNvbHZlIHdoZW4gbW9kYWwgY2xvc2VzXG4gICAgICAgIGNvbnN0IHJlc3VsdF9wcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgIHRoYXQuZGF0YS5yZXNvbHZlX2ZuID0gcmVzb2x2ZTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gU2hvdyBtb2RhbCBhbmQgYmFja2Ryb3BcbiAgICAgICAgdGhpcy5kYXRhLmlzX3Zpc2libGUgPSB0cnVlO1xuXG4gICAgICAgIC8vIEFwcGVuZCB0byBib2R5IHNvIGl0J3Mgb24gdG9wIChkb24ndCBhcHBlbmQgYmFja2Ryb3AgaWYgdXNpbmcgc2hhcmVkKVxuICAgICAgICBpZiAoIXNraXBfYmFja2Ryb3ApIHtcbiAgICAgICAgICAgICQoJ2JvZHknKS5hcHBlbmQodGhpcy4kaWQoJ2JhY2tkcm9wJykpO1xuICAgICAgICB9XG4gICAgICAgICQoJ2JvZHknKS5hcHBlbmQodGhpcy4kKTtcblxuICAgICAgICAvLyBBcHBseSBzaXppbmcgYmVmb3JlIHNob3dpbmdcbiAgICAgICAgdGhpcy5fYXBwbHlfc2l6aW5nKCk7XG5cbiAgICAgICAgLy8gRmFkZSBpbiBtb2RhbCAoYW5kIGJhY2tkcm9wIGlmIG5vdCB1c2luZyBzaGFyZWQpXG4gICAgICAgIGF3YWl0IHRoaXMuX2ZhZGVfaW4oc2hvdWxkX2FuaW1hdGUpO1xuXG4gICAgICAgIC8vIEF1dG8tZm9jdXMgZmlyc3QgaW5wdXQgZWxlbWVudFxuICAgICAgICB0aGlzLl9mb2N1c19maXJzdF9pbnB1dCgpO1xuXG4gICAgICAgIHJldHVybiByZXN1bHRfcHJvbWlzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgYm9keSBjb250ZW50IHdpdGggb3B0aW9uYWwgaWNvblxuICAgICAqL1xuICAgIF9zZXRfYm9keV9jb250ZW50KGJvZHksIGljb24pIHtcbiAgICAgICAgY29uc3QgJGJvZHkgPSB0aGlzLiRpZCgnYm9keScpO1xuICAgICAgICAkYm9keS5lbXB0eSgpO1xuXG4gICAgICAgIC8vIElmIGljb24gcHJvdmlkZWQsIGFkZCBpdFxuICAgICAgICBpZiAoaWNvbikge1xuICAgICAgICAgICAgY29uc3QgJGljb24gPSAkKGA8aSBjbGFzcz1cImJpIGJpLSR7aWNvbn0gbW9kYWwtaWNvblwiPjwvaT5gKTtcbiAgICAgICAgICAgICRib2R5LmFwcGVuZCgkaWNvbik7XG4gICAgICAgICAgICAkYm9keS5hZGRDbGFzcygnaGFzLWljb24nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICRib2R5LnJlbW92ZUNsYXNzKCdoYXMtaWNvbicpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gR2V0IG9yIGNyZWF0ZSBib2R5IGNvbnRlbnQgd3JhcHBlclxuICAgICAgICBsZXQgJGNvbnRlbnQgPSB0aGlzLiRpZCgnYm9keV9jb250ZW50Jyk7XG4gICAgICAgIGlmICghJGNvbnRlbnQuZXhpc3RzKCkpIHtcbiAgICAgICAgICAgICRjb250ZW50ID0gJCgnPGRpdiBjbGFzcz1cIm1vZGFsLWJvZHktY29udGVudFwiPjwvZGl2PicpO1xuICAgICAgICAgICAgJGJvZHkuYXBwZW5kKCRjb250ZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgYm9keSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIC8vIFRleHQgY29udGVudCAtIGVzY2FwZSBhbmQgY29udmVydCBuZXdsaW5lc1xuICAgICAgICAgICAgY29uc3QgZXNjYXBlZCA9ICQoJzxkaXY+JykudGV4dChib2R5KS5odG1sKCkucmVwbGFjZSgvXFxuL2csICc8YnI+Jyk7XG4gICAgICAgICAgICAkY29udGVudC5odG1sKGVzY2FwZWQpO1xuICAgICAgICB9IGVsc2UgaWYgKGJvZHkgaW5zdGFuY2VvZiBqUXVlcnkpIHtcbiAgICAgICAgICAgIC8vIGpRdWVyeSBlbGVtZW50XG4gICAgICAgICAgICAkY29udGVudC5hcHBlbmQoYm9keSk7XG4gICAgICAgIH0gZWxzZSBpZiAoYm9keSAmJiB0eXBlb2YgYm9keSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIC8vIEFzc3VtZSBpdCdzIGEganFodG1sIGNvbXBvbmVudCBpbnN0YW5jZVxuICAgICAgICAgICAgJGNvbnRlbnQuYXBwZW5kKGJvZHkuJCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgYnV0dG9ucyBpbiBmb290ZXJcbiAgICAgKi9cbiAgICBfc2V0X2J1dHRvbnMoKSB7XG4gICAgICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgICAgICBjb25zdCAkZm9vdGVyID0gdGhpcy4kaWQoJ2Zvb3RlcicpO1xuICAgICAgICAkZm9vdGVyLmVtcHR5KCk7XG5cbiAgICAgICAgaWYgKHRoaXMuZGF0YS5idXR0b25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgJGZvb3Rlci5oaWRlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAkZm9vdGVyLnNob3coKTtcblxuICAgICAgICBmb3IgKGxldCBidXR0b25fZGVmIG9mIHRoaXMuZGF0YS5idXR0b25zKSB7XG4gICAgICAgICAgICBjb25zdCAkYnV0dG9uID0gJCgnPGJ1dHRvbj4nKVxuICAgICAgICAgICAgICAgIC5hdHRyKCd0eXBlJywgJ2J1dHRvbicpXG4gICAgICAgICAgICAgICAgLmFkZENsYXNzKCdidG4nKVxuICAgICAgICAgICAgICAgIC5hZGRDbGFzcyhidXR0b25fZGVmLmNsYXNzIHx8ICdidG4tc2Vjb25kYXJ5JylcbiAgICAgICAgICAgICAgICAudGV4dChidXR0b25fZGVmLmxhYmVsIHx8ICdCdXR0b24nKTtcblxuICAgICAgICAgICAgJGJ1dHRvbi5vbignY2xpY2snLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgbGV0IHJlc3VsdCA9IGJ1dHRvbl9kZWYudmFsdWU7XG4gICAgICAgICAgICAgICAgbGV0IGhhZF9jYWxsYmFjayA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgLy8gSWYgYnV0dG9uIGhhcyBhIGNhbGxiYWNrLCBjYWxsIGl0IGFuZCB1c2UgcmV0dXJuIHZhbHVlIGFzIHJlc3VsdFxuICAgICAgICAgICAgICAgIGlmIChidXR0b25fZGVmLmNhbGxiYWNrICYmIHR5cGVvZiBidXR0b25fZGVmLmNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhZF9jYWxsYmFjayA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGF3YWl0IGJ1dHRvbl9kZWYuY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBJZiBjYWxsYmFjayByZXR1cm5lZCBmYWxzZSwga2VlcCBtb2RhbCBvcGVuIChidXQgbm90IGlmIGp1c3QgYnV0dG9uIHZhbHVlIGlzIGZhbHNlKVxuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IGZhbHNlICYmIGhhZF9jYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQ2xvc2UgbW9kYWwgd2l0aCByZXN1bHRcbiAgICAgICAgICAgICAgICB0aGF0LmNsb3NlKHJlc3VsdCk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgJGZvb3Rlci5hcHBlbmQoJGJ1dHRvbik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxjdWxhdGUgYW5kIGFwcGx5IHJlc3BvbnNpdmUgc2l6aW5nXG4gICAgICovXG4gICAgX2FwcGx5X3NpemluZygpIHtcbiAgICAgICAgY29uc3Qgdmlld3BvcnRfd2lkdGggPSAkKHdpbmRvdykud2lkdGgoKTtcbiAgICAgICAgY29uc3Qgdmlld3BvcnRfaGVpZ2h0ID0gJCh3aW5kb3cpLmhlaWdodCgpO1xuICAgICAgICBjb25zdCBpc19tb2JpbGUgPSB2aWV3cG9ydF93aWR0aCA8IDc2ODtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgbWF4IHdpZHRoIGJhc2VkIG9uIHZpZXdwb3J0XG4gICAgICAgIGxldCBtYXhfd2lkdGggPSB0aGlzLmRhdGEubWF4X3dpZHRoO1xuICAgICAgICBjb25zdCB2aWV3cG9ydF9saW1pdCA9IGlzX21vYmlsZSA/IHZpZXdwb3J0X3dpZHRoICogMC45IDogdmlld3BvcnRfd2lkdGggKiAwLjg7XG5cbiAgICAgICAgbWF4X3dpZHRoID0gTWF0aC5taW4obWF4X3dpZHRoLCB2aWV3cG9ydF9saW1pdCk7XG5cbiAgICAgICAgLy8gVHJ5IHRvIGNvbnN0cmFpbiB0byA2MCUgd2lkdGggZm9yIGJldHRlciBwcm9wb3J0aW9ucyBvbiBkZXNrdG9wXG4gICAgICAgIGlmICghaXNfbW9iaWxlKSB7XG4gICAgICAgICAgICBjb25zdCBwcmVmZXJyZWRfd2lkdGggPSB2aWV3cG9ydF93aWR0aCAqIDAuNjtcbiAgICAgICAgICAgIGlmIChwcmVmZXJyZWRfd2lkdGggPCBtYXhfd2lkdGgpIHtcbiAgICAgICAgICAgICAgICBtYXhfd2lkdGggPSBwcmVmZXJyZWRfd2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBcHBseSB3aWR0aFxuICAgICAgICB0aGlzLiRpZCgnZGlhbG9nJykuY3NzKCdtYXgtd2lkdGgnLCBtYXhfd2lkdGggKyAncHgnKTtcblxuICAgICAgICAvLyBDaGVjayBpZiBjb250ZW50IGV4Y2VlZHMgODAlIGhlaWdodFxuICAgICAgICBjb25zdCBjb250ZW50X2hlaWdodCA9IHRoaXMuJGlkKCdkaWFsb2cnKS5vdXRlckhlaWdodCgpO1xuICAgICAgICBjb25zdCBtYXhfaGVpZ2h0ID0gdmlld3BvcnRfaGVpZ2h0ICogMC44O1xuXG4gICAgICAgIGlmIChjb250ZW50X2hlaWdodCA+IG1heF9oZWlnaHQpIHtcbiAgICAgICAgICAgIC8vIEVuYWJsZSBzY3JvbGxpbmdcbiAgICAgICAgICAgIHRoaXMuJGlkKCdkaWFsb2cnKS5jc3MoJ21heC1oZWlnaHQnLCBtYXhfaGVpZ2h0ICsgJ3B4Jyk7XG4gICAgICAgICAgICB0aGlzLiRpZCgnYm9keScpLmNzcyh7XG4gICAgICAgICAgICAgICAgJ292ZXJmbG93LXknOiAnYXV0bycsXG4gICAgICAgICAgICAgICAgJ21heC1oZWlnaHQnOiBtYXhfaGVpZ2h0IC0gMTUwICsgJ3B4JywgLy8gQWNjb3VudCBmb3IgaGVhZGVyL2Zvb3RlclxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBSZXNldCBzY3JvbGxpbmdcbiAgICAgICAgICAgIHRoaXMuJGlkKCdkaWFsb2cnKS5jc3MoJ21heC1oZWlnaHQnLCAnJyk7XG4gICAgICAgICAgICB0aGlzLiRpZCgnYm9keScpLmNzcyh7XG4gICAgICAgICAgICAgICAgJ292ZXJmbG93LXknOiAnJyxcbiAgICAgICAgICAgICAgICAnbWF4LWhlaWdodCc6ICcnLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBNb2JpbGUgZWRnZSBzcGFjaW5nXG4gICAgICAgIGlmIChpc19tb2JpbGUpIHtcbiAgICAgICAgICAgIHRoaXMuJGlkKCdkaWFsb2cnKS5jc3MoJ21hcmdpbicsICc1JScpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy4kaWQoJ2RpYWxvZycpLmNzcygnbWFyZ2luJywgJzAnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNob3cgYW5pbWF0aW9uIChpbnN0YW50IG9yIHdpdGggZmx5LWluKVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gYW5pbWF0ZSAtIFdoZXRoZXIgdG8gYW5pbWF0ZSB0aGUgbW9kYWwgZW50cmFuY2VcbiAgICAgKi9cbiAgICBhc3luYyBfZmFkZV9pbihhbmltYXRlID0gZmFsc2UpIHtcbiAgICAgICAgaWYgKGFuaW1hdGUpIHtcbiAgICAgICAgICAgIC8vIEluaXRpYWwgc3RhdGU6IG1vZGFsIHBvc2l0aW9uZWQgYWJvdmUgZmluYWwgcG9zaXRpb25cbiAgICAgICAgICAgIHRoaXMuJC5jc3MoJ2Rpc3BsYXknLCAnZmxleCcpLmNzcygnb3BhY2l0eScsICcwJyk7XG4gICAgICAgICAgICB0aGlzLiRpZCgnbW9kYWwnKS5jc3Moe1xuICAgICAgICAgICAgICAgICd0cmFuc2Zvcm0nOiAndHJhbnNsYXRlKDAsIC01MHB4KScsXG4gICAgICAgICAgICAgICAgJ29wYWNpdHknOiAnMCdcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy4kaWQoJ2JhY2tkcm9wJykuY3NzKCdkaXNwbGF5JywgJ2Jsb2NrJykuYWRkQ2xhc3MoJ3Nob3cnKTtcblxuICAgICAgICAgICAgLy8gRm9yY2UgcmVmbG93XG4gICAgICAgICAgICB0aGlzLiRpZCgnbW9kYWwnKVswXS5vZmZzZXRIZWlnaHQ7XG5cbiAgICAgICAgICAgIC8vIFRyaWdnZXIgYW5pbWF0aW9uXG4gICAgICAgICAgICB0aGlzLiRpZCgnbW9kYWwnKS5hZGRDbGFzcygnc2hvdycpLmNzcyh7XG4gICAgICAgICAgICAgICAgJ3RyYW5zZm9ybSc6ICd0cmFuc2xhdGUoMCwgMCknLFxuICAgICAgICAgICAgICAgICdvcGFjaXR5JzogJzEnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuJC5jc3MoJ29wYWNpdHknLCAnMScpO1xuXG4gICAgICAgICAgICAvLyBXYWl0IGZvciBhbmltYXRpb24gdG8gY29tcGxldGVcbiAgICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxNTApKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIERpc2FibGUgdHJhbnNpdGlvbnMgdGVtcG9yYXJpbHkgZm9yIGluc3RhbnQgZGlzcGxheVxuICAgICAgICAgICAgdGhpcy4kaWQoJ2RpYWxvZycpLmNzcygndHJhbnNpdGlvbicsICdub25lJyk7XG5cbiAgICAgICAgICAgIC8vIFNob3cgbW9kYWwgYW5kIGJhY2tkcm9wIGluc3RhbnRseVxuICAgICAgICAgICAgdGhpcy4kLmNzcygnZGlzcGxheScsICdmbGV4JykuY3NzKCdvcGFjaXR5JywgJzEnKTtcbiAgICAgICAgICAgIHRoaXMuJGlkKCdtb2RhbCcpLmFkZENsYXNzKCdzaG93JykuY3NzKCdvcGFjaXR5JywgJzEnKTtcbiAgICAgICAgICAgIHRoaXMuJGlkKCdiYWNrZHJvcCcpLmNzcygnZGlzcGxheScsICdibG9jaycpLmFkZENsYXNzKCdzaG93Jyk7XG5cbiAgICAgICAgICAgIC8vIEZvcmNlIHJlZmxvdyB0byBhcHBseSB0aGUgbm8tdHJhbnNpdGlvbiBzdGF0ZVxuICAgICAgICAgICAgdGhpcy4kaWQoJ2RpYWxvZycpWzBdLm9mZnNldEhlaWdodDtcblxuICAgICAgICAgICAgLy8gUmUtZW5hYmxlIHRyYW5zaXRpb25zIGZvciBmdXR1cmUgYW5pbWF0aW9uc1xuICAgICAgICAgICAgdGhpcy4kaWQoJ2RpYWxvZycpLmNzcygndHJhbnNpdGlvbicsICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb2N1cyB0aGUgZmlyc3QgaW5wdXQgZWxlbWVudCBpbiB0aGUgbW9kYWxcbiAgICAgKi9cbiAgICBfZm9jdXNfZmlyc3RfaW5wdXQoKSB7XG4gICAgICAgIC8vIEZpbmQgZmlyc3QgaW5wdXQvdGV4dGFyZWEvc2VsZWN0IGluIG1vZGFsIGJvZHlcbiAgICAgICAgY29uc3QgJGZpcnN0X2lucHV0ID0gdGhpcy4kaWQoJ2JvZHknKS5maW5kKCdpbnB1dDpub3QoW3R5cGU9XCJoaWRkZW5cIl0pLCB0ZXh0YXJlYSwgc2VsZWN0JykuZmlyc3QoKTtcbiAgICAgICAgaWYgKCRmaXJzdF9pbnB1dC5leGlzdHMoKSkge1xuICAgICAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcbiAgICAgICAgICAgICAgICAkZmlyc3RfaW5wdXQuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICAvLyBTZWxlY3QgdGV4dCBpZiBpdCdzIGFuIGlucHV0IHdpdGggZXhpc3RpbmcgdmFsdWVcbiAgICAgICAgICAgICAgICBpZiAoJGZpcnN0X2lucHV0LmlzKCdpbnB1dFt0eXBlPVwidGV4dFwiXSwgaW5wdXRbdHlwZT1cImVtYWlsXCJdJykgJiYgJGZpcnN0X2lucHV0LnZhbCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICRmaXJzdF9pbnB1dC5zZWxlY3QoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsb3NlIHRoZSBtb2RhbCBpbnN0YW50bHlcbiAgICAgKi9cbiAgICBhc3luYyBjbG9zZShyZXN1bHQpIHtcbiAgICAgICAgY29uc3QgdGhhdCA9IHRoaXM7XG5cbiAgICAgICAgLy8gTWFyayBhcyBub3QgdmlzaWJsZVxuICAgICAgICB0aGlzLmRhdGEuaXNfdmlzaWJsZSA9IGZhbHNlO1xuXG4gICAgICAgIC8vIFJlbW92ZSBldmVudCBsaXN0ZW5lcnNcbiAgICAgICAgJChkb2N1bWVudCkub2ZmKCdrZXlkb3duLnJzeF9tb2RhbF8nICsgdGhpcy5fY2lkKTtcbiAgICAgICAgJCh3aW5kb3cpLm9mZigncmVzaXplLnJzeF9tb2RhbF8nICsgdGhpcy5fY2lkKTtcblxuICAgICAgICAvLyBIaWRlIGluc3RhbnRseSAobm8gZmFkZSBvdXQpXG4gICAgICAgIHRoaXMuJC5oaWRlKCk7XG4gICAgICAgIHRoaXMuJGlkKCdiYWNrZHJvcCcpLmhpZGUoKTtcblxuICAgICAgICAvLyBSZW1vdmUgZnJvbSBET01cbiAgICAgICAgdGhpcy4kLnJlbW92ZSgpO1xuICAgICAgICB0aGlzLiRpZCgnYmFja2Ryb3AnKS5yZW1vdmUoKTtcblxuICAgICAgICAvLyBSZXNvbHZlIHByb21pc2VcbiAgICAgICAgaWYgKHRoaXMuZGF0YS5yZXNvbHZlX2ZuKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGEucmVzb2x2ZV9mbihyZXN1bHQpO1xuICAgICAgICAgICAgdGhpcy5kYXRhLnJlc29sdmVfZm4gPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXBwbHkgdmFsaWRhdGlvbiBlcnJvcnMgdG8gZm9ybSBmaWVsZHMgaW4gbW9kYWwgYm9keVxuICAgICAqL1xuICAgIGFwcGx5X2Vycm9ycyhlcnJvcnMpIHtcbiAgICAgICAgLy8gVXNlIEZvcm1fVXRpbHMgdG8gYXBwbHkgZXJyb3JzIHRvIGVsZW1lbnRzIHdpdGhpbiBtb2RhbCBib2R5XG4gICAgICAgIEZvcm1fVXRpbHMuYXBwbHlfZm9ybV9lcnJvcnModGhpcy4kaWQoJ2JvZHknKSwgZXJyb3JzKTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTUEsU0FBUyxTQUFTQyxnQkFBZ0IsQ0FBQztFQUNyQ0MsU0FBU0EsQ0FBQSxFQUFHO0lBQ1IsSUFBSSxDQUFDQyxJQUFJLENBQUNDLEtBQUssR0FBRyxFQUFFO0lBQ3BCLElBQUksQ0FBQ0QsSUFBSSxDQUFDRSxZQUFZLEdBQUcsSUFBSTtJQUM3QixJQUFJLENBQUNGLElBQUksQ0FBQ0csT0FBTyxHQUFHLEVBQUU7SUFDdEIsSUFBSSxDQUFDSCxJQUFJLENBQUNJLFFBQVEsR0FBRyxJQUFJO0lBQ3pCLElBQUksQ0FBQ0osSUFBSSxDQUFDSyxTQUFTLEdBQUcsR0FBRztJQUN6QixJQUFJLENBQUNMLElBQUksQ0FBQ00sZUFBZSxHQUFHLElBQUk7SUFDaEMsSUFBSSxDQUFDTixJQUFJLENBQUNPLFVBQVUsR0FBRyxLQUFLO0lBQzVCLElBQUksQ0FBQ1AsSUFBSSxDQUFD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
|