Commit b727d575 authored by Esmael El-Moslimany's avatar Esmael El-Moslimany Committed by Commit Bot

Extensions WebUI: options dialog, debounce size updates and delay making opaque

Bug: 904942
Change-Id: Ib2d2370699988a95e6e6518988303bc9a4ed4a4d
Reviewed-on: https://chromium-review.googlesource.com/c/1340905
Commit-Queue: Esmael El-Moslimany <aee@chromium.org>
Reviewed-by: default avatarScott Chen <scottchen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#609082}
parent d470cee7
...@@ -47,6 +47,15 @@ ...@@ -47,6 +47,15 @@
height: 100%; height: 100%;
min-height: initial; min-height: initial;
}; };
--cr-dialog-native: {
opacity: 0;
/* When loading, it's possible for an size update to follow after the
initial size update. The debounce time on size updates is 50ms.
A 100ms delay for the opacity transition will allow two updates to
occur without showing the dialog resizing to the user. */
transition: opacity 100ms ease 100ms;
};
} }
</style> </style>
......
...@@ -44,30 +44,31 @@ cr.define('extensions', function() { ...@@ -44,30 +44,31 @@ cr.define('extensions', function() {
}, },
/** @private {?Function} */ /** @private {?Function} */
boundResizeListener_: null, boundUpdateDialogSize_: null,
/** @private {?{height: number, width: number}} */
preferredSize_: null,
get open() { get open() {
return /** @type {!CrDialogElement} */ (this.$.dialog).open; return this.$.dialog.open;
}, },
/** /**
* Resizes the dialog to the given width/height, taking into account the * Resizes the dialog to the width/height stored in |preferredSize_|, taking
* window width/height. * into account the window width/height.
* @param {number} width The desired height of the dialog contents.
* @param {number} height The desired width of the dialog contents.
* @private * @private
*/ */
updateDialogSize_: function(width, height) { updateDialogSize_: function() {
const headerHeight = this.$.body.offsetTop; const headerHeight = this.$.body.offsetTop;
const maxHeight = Math.min(0.9 * window.innerHeight, MAX_HEIGHT); const maxHeight = Math.min(0.9 * window.innerHeight, MAX_HEIGHT);
const effectiveHeight = Math.min(maxHeight, headerHeight + height); const effectiveHeight =
const effectiveWidth = Math.max(MIN_WIDTH, width); Math.min(maxHeight, headerHeight + this.preferredSize_.height);
const effectiveWidth = Math.max(MIN_WIDTH, this.preferredSize_.width);
// Get a reference to the inner native <dialog>. const nativeDialog = this.$.dialog.getNative();
const nativeDialog =
/** @type {!CrDialogElement} */ (this.$.dialog).getNative();
nativeDialog.style.height = `${effectiveHeight}px`; nativeDialog.style.height = `${effectiveHeight}px`;
nativeDialog.style.width = `${effectiveWidth}px`; nativeDialog.style.width = `${effectiveWidth}px`;
nativeDialog.style.opacity = '1';
}, },
/** @param {chrome.developerPrivate.ExtensionInfo} data */ /** @param {chrome.developerPrivate.ExtensionInfo} data */
...@@ -77,44 +78,31 @@ cr.define('extensions', function() { ...@@ -77,44 +78,31 @@ cr.define('extensions', function() {
if (!this.extensionOptions_) if (!this.extensionOptions_)
this.extensionOptions_ = document.createElement('ExtensionOptions'); this.extensionOptions_ = document.createElement('ExtensionOptions');
this.extensionOptions_.extension = this.data_.id; this.extensionOptions_.extension = this.data_.id;
this.extensionOptions_.onclose = this.close.bind(this); this.extensionOptions_.onclose = () => this.$.dialog.close();
let preferredSize = null; const boundUpdateDialogSize = this.updateDialogSize_.bind(this);
this.boundUpdateDialogSize_ = boundUpdateDialogSize;
this.extensionOptions_.onpreferredsizechanged = e => { this.extensionOptions_.onpreferredsizechanged = e => {
preferredSize = e;
if (!this.$.dialog.open) if (!this.$.dialog.open)
this.$.dialog.showModal(); this.$.dialog.showModal();
// Updating the dialog size can result in a preferred size change, so this.preferredSize_ = e;
// wait until request animation frame fires before updating the dialog this.debounce('updateDialogSize_', boundUpdateDialogSize, 50);
// size. This hysteresis prevents the preferred size from oscillating
// (see: https://crbug.com/882835).
requestAnimationFrame(() => {
this.updateDialogSize_(preferredSize.width, preferredSize.height);
});
};
this.boundResizeListener_ = () => {
this.updateDialogSize_(preferredSize.width, preferredSize.height);
}; };
// Add a 'resize' such that the dialog is resized when window size // Add a 'resize' such that the dialog is resized when window size
// changes. // changes.
window.addEventListener('resize', this.boundResizeListener_); window.addEventListener('resize', this.boundUpdateDialogSize_);
this.$.body.appendChild(this.extensionOptions_); this.$.body.appendChild(this.extensionOptions_);
}); });
}, },
close: function() {
/** @type {!CrDialogElement} */ (this.$.dialog).close();
},
/** @private */ /** @private */
onClose_: function() { onClose_: function() {
this.extensionOptions_.onpreferredsizechanged = null; this.extensionOptions_.onpreferredsizechanged = null;
if (this.boundResizeListener_) { if (this.boundUpdateDialogSize_) {
window.removeEventListener('resize', this.boundResizeListener_); window.removeEventListener('resize', this.boundUpdateDialogSize_);
this.boundResizeListener_ = null; this.boundUpdateDialogSize_ = null;
} }
const currentPage = extensions.navigation.getCurrentPage(); const currentPage = extensions.navigation.getCurrentPage();
......
...@@ -41,10 +41,11 @@ cr.define('extension_options_dialog_tests', function() { ...@@ -41,10 +41,11 @@ cr.define('extension_options_dialog_tests', function() {
assertFalse(isDialogVisible()); assertFalse(isDialogVisible());
optionsDialog.show(data); optionsDialog.show(data);
return test_util.eventToPromise('cr-dialog-open', optionsDialog) return test_util.eventToPromise('cr-dialog-open', optionsDialog)
.then(function() { .then(() => {
// The dialog size is set asynchronously (see onpreferredsizechanged // Wait more than 50ms for the debounced size update.
// in options_dialog.js) so wait one frame. return new Promise(r => setTimeout(r, 100));
requestAnimationFrame(function() { })
.then(() => {
assertTrue(isDialogVisible()); assertTrue(isDialogVisible());
const dialogElement = optionsDialog.$.dialog.getNative(); const dialogElement = optionsDialog.$.dialog.getNative();
...@@ -61,7 +62,6 @@ cr.define('extension_options_dialog_tests', function() { ...@@ -61,7 +62,6 @@ cr.define('extension_options_dialog_tests', function() {
}); });
}); });
}); });
});
return { return {
suiteName: suiteName, suiteName: suiteName,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment