Commit 0d3fa109 authored by Jon Mann's avatar Jon Mann Committed by Commit Bot

Wi-Fi List: Keep focus on active row when update is received.

This fixes a long standing bug where the focus moved back up
to the first network when an update to the list of available networks
came in.

Bug: 720274
Change-Id: Iee036aa649a74eef1b1743317a07b35061e08d3c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2480712Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Commit-Queue: Jon Mann <jonmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#819297}
parent 64537f00
...@@ -205,6 +205,7 @@ js_library("network_list") { ...@@ -205,6 +205,7 @@ js_library("network_list") {
deps = [ deps = [
":network_list_types", ":network_list_types",
"//ui/webui/resources/cr_elements:cr_scrollable_behavior", "//ui/webui/resources/cr_elements:cr_scrollable_behavior",
"//ui/webui/resources/js:list_property_update_behavior",
] ]
} }
...@@ -214,6 +215,7 @@ js_library("network_list_item") { ...@@ -214,6 +215,7 @@ js_library("network_list_item") {
":network_list_types", ":network_list_types",
"//ui/webui/resources/js:assert", "//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior", "//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js/cr/ui:focus_row_behavior",
] ]
} }
...@@ -277,6 +279,10 @@ js_type_check("closure_compile_module") { ...@@ -277,6 +279,10 @@ js_type_check("closure_compile_module") {
":network_siminfo.m", ":network_siminfo.m",
":onc_mojo.m", ":onc_mojo.m",
] ]
# closure_flags = default_closure_args + [
# "js_module_root=../../ui/webui/resources/js/",
# "js_module_root=./gen/ui/webui/resources/js/"]
} }
js_library("mojo_interface_provider.m") { js_library("mojo_interface_provider.m") {
...@@ -437,6 +443,7 @@ js_library("network_list.m") { ...@@ -437,6 +443,7 @@ js_library("network_list.m") {
"//third_party/polymer/v3_0/components-chromium/iron-list:iron-list", "//third_party/polymer/v3_0/components-chromium/iron-list:iron-list",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/cr_elements:cr_scrollable_behavior.m", "//ui/webui/resources/cr_elements:cr_scrollable_behavior.m",
"//ui/webui/resources/js:list_property_update_behavior.m",
] ]
extra_deps = [ ":network_list_module" ] extra_deps = [ ":network_list_module" ]
} }
...@@ -446,6 +453,7 @@ js_library("network_list_item.m") { ...@@ -446,6 +453,7 @@ js_library("network_list_item.m") {
deps = [ deps = [
":network_list_types.m", ":network_list_types.m",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/js/cr/ui:focus_row_behavior.m",
] ]
extra_deps = [ ":network_list_item_module" ] extra_deps = [ ":network_list_item_module" ]
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
<link rel="import" href="../../../cr_elements/shared_style_css.html"> <link rel="import" href="../../../cr_elements/shared_style_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
<link rel="import" href="../../../html/list_property_update_behavior.html">
<dom-module id="network-list"> <dom-module id="network-list">
<template> <template>
...@@ -36,13 +37,18 @@ ...@@ -36,13 +37,18 @@
</style> </style>
<div id="container" class="layout vertical flex" scrollable <div id="container" class="layout vertical flex" scrollable
no-bottom-scroll-border$="[[noBottomScrollBorder]]"> no-bottom-scroll-border$="[[noBottomScrollBorder]]">
<iron-list id="networkList" selection-enabled items="[[listItems_]]" <iron-list id="networkList" items="[[listItems_]]"
scroll-target="container" selected-item="{{selectedItem}}"> scroll-target="container" preserve-focus>
<template> <template>
<network-list-item item="[[item]]" <network-list-item item="[[item]]"
show-technology-badge="[[showTechnologyBadge]]" show-technology-badge="[[showTechnologyBadge]]"
show-buttons="[[showButtons]]" tabindex$="[[tabIndex]]" show-buttons="[[showButtons]]"
tabindex$="[[tabIndex]]"
focus-row-index="[[index]]"
iron-list-tab-index="[[tabIndex]]"
activation-unavailable="[[activationUnavailable]]" activation-unavailable="[[activationUnavailable]]"
last-focused="{{lastFocused_}}"
list-blurred="{{listBlurred_}}"
device-state="[[deviceState]]"> device-state="[[deviceState]]">
</network-list-item> </network-list-item>
</template> </template>
......
...@@ -74,12 +74,49 @@ Polymer({ ...@@ -74,12 +74,49 @@ Polymer({
return []; return [];
}, },
}, },
/**
* Used by FocusRowBehavior to track the last focused element on a row.
* @private
*/
lastFocused_: Object,
/**
* Used by FocusRowBehavior to track if the list has been blurred.
* @private
*/
listBlurred_: Boolean,
}, },
behaviors: [CrScrollableBehavior], behaviors: [CrScrollableBehavior, ListPropertyUpdateBehavior],
observers: ['updateListItems_(networks, customItems)'], observers: ['updateListItems_(networks, customItems)'],
/** @type {ResizeObserver} used to observer size changes to this element */
resizeObserver_: null,
/** @override */
attached() {
// This is a required work around to get the iron-list to display on first
// view. Currently iron-list won't generate item elements on attach if the
// element is not visible. Because there are some instances where this
// component might not be visible when the items are bound, we listen for
// resize events and manually call notifyResize on the iron-list
this.resizeObserver_ = new ResizeObserver(entries => {
const networkList =
/** @type {IronListElement} */ (this.$$('#networkList'));
if (networkList) {
networkList.notifyResize();
}
});
this.resizeObserver_.observe(this);
},
/** @override */
detached() {
this.resizeObserver_.disconnect();
},
/** @private {boolean} */ /** @private {boolean} */
focusRequested_: false, focusRequested_: false,
...@@ -89,16 +126,15 @@ Polymer({ ...@@ -89,16 +126,15 @@ Polymer({
}, },
/** @private */ /** @private */
updateListItems_() { updateListItems_: function() {
this.saveScroll(/** @type {!IronListElement} */ (this.$.networkList)); const beforeNetworks =
const beforeNetworks = this.customItems.filter(function(item) { this.customItems.filter(n => n.showBeforeNetworksList === true);
return item.showBeforeNetworksList === true; const afterNetworks =
}); this.customItems.filter(n => n.showBeforeNetworksList === false);
const afterNetworks = this.customItems.filter(function(item) { const newList = beforeNetworks.concat(this.networks, afterNetworks);
return item.showBeforeNetworksList !== true;
}); this.updateList('listItems_', item => item.guid, newList);
this.listItems_ = beforeNetworks.concat(this.networks, afterNetworks);
this.restoreScroll(/** @type {!IronListElement} */ (this.$.networkList));
this.updateScrollableContents(); this.updateScrollableContents();
if (this.focusRequested_) { if (this.focusRequested_) {
this.async(function() { this.async(function() {
...@@ -117,28 +153,4 @@ Polymer({ ...@@ -117,28 +153,4 @@ Polymer({
item.focus(); item.focus();
this.focusRequested_ = false; this.focusRequested_ = false;
}, },
/**
* Use iron-list selection (which is not the same as focus) to trigger
* tap (requires selection-enabled) or keyboard selection.
* @private
*/
selectedItemChanged_() {
if (this.selectedItem) {
this.onItemAction_(this.selectedItem);
}
},
/**
* @param {!NetworkList.NetworkListItemType} item
* @private
*/
onItemAction_(item) {
if (item.hasOwnProperty('customItemName')) {
this.fire('custom-item-selected', item);
} else {
this.fire('selected', item);
this.focusRequested_ = true;
}
},
}); });
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
<link rel="import" href="../../../cr_elements/shared_style_css.html"> <link rel="import" href="../../../cr_elements/shared_style_css.html">
<link rel="import" href="../../../cr_elements/shared_vars_css.html"> <link rel="import" href="../../../cr_elements/shared_vars_css.html">
<link rel="import" href="../../../html/i18n_behavior.html"> <link rel="import" href="../../../html/i18n_behavior.html">
<link rel="import" href="../../../html/cr/ui/focus_row_behavior.html">
<link rel="import" href="cr_policy_network_behavior_mojo.html"> <link rel="import" href="cr_policy_network_behavior_mojo.html">
<link rel="import" href="network_icon.html"> <link rel="import" href="network_icon.html">
<link rel="import" href="network_list_types.html"> <link rel="import" href="network_list_types.html">
...@@ -21,6 +22,7 @@ ...@@ -21,6 +22,7 @@
} }
#divOuter { #divOuter {
height: 100%;
padding-inline-end: var(--cr-icon-ripple-padding); padding-inline-end: var(--cr-icon-ripple-padding);
} }
...@@ -54,9 +56,23 @@ ...@@ -54,9 +56,23 @@
cr-policy-indicator { cr-policy-indicator {
padding: 0 var(--cr-controlled-by-spacing); padding: 0 var(--cr-controlled-by-spacing);
} }
#wrapper {
height: 100%;
}
</style> </style>
<div id="wrapper" focus-row-container
class="layout horizontal center flex">
<div id="divOuter" <div id="divOuter"
class="layout horizontal center flex" actionable> class="layout horizontal center flex"
actionable
focus-row-control
selectable
aria-label$="[[rowLabel]]"
role="button"
focus-type="rowWrapper"
on-keydown="onKeydown_"
on-click="onSelected_">
<template is="dom-if" if="[[networkState]]"> <template is="dom-if" if="[[networkState]]">
<network-icon is-list-item <network-icon is-list-item
show-technology-badge="[[showTechnologyBadge]]" show-technology-badge="[[showTechnologyBadge]]"
...@@ -81,14 +97,20 @@ ...@@ -81,14 +97,20 @@
networkState.source)]]"> networkState.source)]]">
</cr-policy-indicator> </cr-policy-indicator>
</template> </template>
<template is="dom-if" <template is="dom-if" if="[[isSubpageButtonVisible_(networkState, showButtons)]]" restamp>
if="[[isSubpageButtonVisible_(networkState, showButtons)]]" restamp> <div>
<cr-icon-button class="subpage-arrow" id="subpage-button" <cr-icon-button class="subpage-arrow"
on-click="onSubpageArrowClick_" tabindex$="[[tabindex]]" id="subpage-button"
aria-label$="[[buttonLabel]]"> on-click="onSubpageArrowClick_"
tabindex$="[[tabindex]]"
aria-label$="[[buttonLabel]]"
focus-row-control
focus-type="subpageButton">
</cr-icon-button> </cr-icon-button>
</div>
</template> </template>
</div> </div>
</div>
</template> </template>
<script src="network_list_item.js"></script> <script src="network_list_item.js"></script>
</dom-module> </dom-module>
...@@ -13,6 +13,7 @@ Polymer({ ...@@ -13,6 +13,7 @@ Polymer({
behaviors: [ behaviors: [
CrPolicyNetworkBehaviorMojo, CrPolicyNetworkBehaviorMojo,
I18nBehavior, I18nBehavior,
cr.ui.FocusRowBehavior,
], ],
properties: { properties: {
...@@ -45,7 +46,6 @@ Polymer({ ...@@ -45,7 +46,6 @@ Polymer({
tabindex: { tabindex: {
type: Number, type: Number,
value: -1, value: -1,
reflectToAttribute: true,
}, },
/** /**
...@@ -53,11 +53,10 @@ Polymer({ ...@@ -53,11 +53,10 @@ Polymer({
* added as an attribute on this top-level network-list-item, and can * added as an attribute on this top-level network-list-item, and can
* be used by any sub-element which applies it. * be used by any sub-element which applies it.
*/ */
ariaLabel: { rowLabel: {
type: String, type: String,
notify: true, notify: true,
reflectToAttribute: true, computed: 'getRowLabel_(item, networkState)',
computed: 'getAriaLabel_(item, networkState)',
}, },
buttonLabel: { buttonLabel: {
...@@ -162,7 +161,7 @@ Polymer({ ...@@ -162,7 +161,7 @@ Polymer({
* @return {string} * @return {string}
* @private * @private
*/ */
getAriaLabel_() { getRowLabel_() {
const NetworkType = chromeos.networkConfig.mojom.NetworkType; const NetworkType = chromeos.networkConfig.mojom.NetworkType;
const OncSource = chromeos.networkConfig.mojom.OncSource; const OncSource = chromeos.networkConfig.mojom.OncSource;
const SecurityType = chromeos.networkConfig.mojom.SecurityType; const SecurityType = chromeos.networkConfig.mojom.SecurityType;
...@@ -344,15 +343,11 @@ Polymer({ ...@@ -344,15 +343,11 @@ Polymer({
* @private * @private
*/ */
onKeydown_(event) { onKeydown_(event) {
// The only key event handled by this element is pressing Enter when the if (event.key !== 'Enter' && event.key !== ' ') {
// subpage arrow is focused.
if (event.key !== 'Enter' ||
!this.isSubpageButtonVisible_(this.networkState, this.showButtons) ||
this.$$('#subpage-button') !== this.shadowRoot.activeElement) {
return; return;
} }
this.fireShowDetails_(event); this.onSelected_(event);
// The default event for pressing Enter on a focused button is to simulate a // The default event for pressing Enter on a focused button is to simulate a
// click on the button. Prevent this action, since it would navigate a // click on the button. Prevent this action, since it would navigate a
...@@ -361,6 +356,22 @@ Polymer({ ...@@ -361,6 +356,22 @@ Polymer({
event.preventDefault(); event.preventDefault();
}, },
/**
* @param {!Event} event
* @private
*/
onSelected_(event) {
if (this.isSubpageButtonVisible_(this.networkState, this.showButtons) &&
this.$$('#subpage-button') === this.shadowRoot.activeElement) {
this.fireShowDetails_(event);
} else if (this.item.hasOwnProperty('customItemName')) {
this.fire('custom-item-selected', this.item);
} else {
this.fire('selected', this.item);
this.focusRequested_ = true;
}
},
/** /**
* @param {!MouseEvent} event * @param {!MouseEvent} event
* @private * @private
......
...@@ -128,7 +128,7 @@ Polymer({ ...@@ -128,7 +128,7 @@ Polymer({
for (const network of networkList.children) { for (const network of networkList.children) {
if (network.is === 'network-list-item' && if (network.is === 'network-list-item' &&
network.$$('#divText').children[0].innerText === name) { network.$$('#divText').children[0].innerText === name) {
return network; return network.shadowRoot.getElementById('divOuter');
} }
} }
return null; return null;
......
...@@ -39,5 +39,7 @@ cr_components_chromeos_auto_imports = [ ...@@ -39,5 +39,7 @@ cr_components_chromeos_auto_imports = [
"ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.html|recordLockScreenProgress,LockScreenProgress", "ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.html|recordLockScreenProgress,LockScreenProgress",
"ui/webui/resources/cr_components/chromeos/cellular_setup/webview_post_util.html|postDeviceDataToWebview", "ui/webui/resources/cr_components/chromeos/cellular_setup/webview_post_util.html|postDeviceDataToWebview",
"ui/webui/resources/html/assert.html|assert,assertNotReached", "ui/webui/resources/html/assert.html|assert,assertNotReached",
"ui/webui/resources/html/cr/ui/focus_row_behavior.html|FocusRowBehavior",
"ui/webui/resources/html/list_property_update_behavior.html|ListPropertyUpdateBehavior",
"ui/webui/resources/html/polymer.html|Polymer,flush,html", "ui/webui/resources/html/polymer.html|Polymer,flush,html",
] ]
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