Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * Responds to route changes by expanding, collapsing, or scrolling to sections | 6 * Responds to route changes by expanding, collapsing, or scrolling to sections |
| 7 * on the page. Expanded sections take up the full height of the container. At | 7 * on the page. Expanded sections take up the full height of the container. At |
| 8 * most one section should be expanded at any given time. | 8 * most one section should be expanded at any given time. |
| 9 * @polymerBehavior MainPageBehavior | 9 * @polymerBehavior MainPageBehavior |
| 10 */ | 10 */ |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 | 87 |
| 88 // TODO(dschuyler): This doesn't set the flag in the case of going to or | 88 // TODO(dschuyler): This doesn't set the flag in the case of going to or |
| 89 // from the main page. It seems sensible to set the flag in those cases, | 89 // from the main page. It seems sensible to set the flag in those cases, |
| 90 // unfortunately bug 708465 happens. Figure out why that is and then set | 90 // unfortunately bug 708465 happens. Figure out why that is and then set |
| 91 // this flag more broadly. | 91 // this flag more broadly. |
| 92 if (oldRoute && oldRoute.isSubpage() && newRoute.isSubpage()) | 92 if (oldRoute && oldRoute.isSubpage() && newRoute.isSubpage()) |
| 93 this.isSubpageAnimating = true; | 93 this.isSubpageAnimating = true; |
| 94 | 94 |
| 95 // For previously uncreated pages (including on first load), allow the page | 95 // For previously uncreated pages (including on first load), allow the page |
| 96 // to render before scrolling to or expanding the section. | 96 // to render before scrolling to or expanding the section. |
| 97 if (!oldRoute || this.scrollHeight == 0) | 97 if (!oldRoute || this.scrollHeight == 0) { |
| 98 setTimeout(this.tryTransitionToSection_.bind(this, scrollToSection)); | 98 this.fire('hide-container'); |
|
michaelpg
2017/05/24 21:29:40
Can we limit this event to the !oldRoute case? In
scottchen
2017/05/25 19:28:30
I think at this point it's probably easier to sepa
| |
| 99 else | 99 setTimeout(function() { |
| 100 this.fire('show-container'); | |
| 101 this.tryTransitionToSection_(scrollToSection, true); | |
| 102 }.bind(this)); | |
| 103 } else | |
| 100 this.tryTransitionToSection_(scrollToSection); | 104 this.tryTransitionToSection_(scrollToSection); |
| 101 }, | 105 }, |
| 102 | 106 |
| 103 /** | 107 /** |
| 104 * When exiting search mode, we need to make another attempt to scroll to | 108 * When exiting search mode, we need to make another attempt to scroll to |
| 105 * the correct section, since it has just been re-rendered. | 109 * the correct section, since it has just been re-rendered. |
| 106 * @private | 110 * @private |
| 107 */ | 111 */ |
| 108 inSearchModeChanged_: function(inSearchMode) { | 112 inSearchModeChanged_: function(inSearchMode) { |
| 109 if (!this.isAttached) | 113 if (!this.isAttached) |
| 110 return; | 114 return; |
| 111 | 115 |
| 112 if (!inSearchMode) | 116 if (!inSearchMode) |
| 113 this.tryTransitionToSection_(!settings.lastRouteChangeWasPopstate()); | 117 this.tryTransitionToSection_(!settings.lastRouteChangeWasPopstate()); |
| 114 }, | 118 }, |
| 115 | 119 |
| 116 /** | 120 /** |
| 117 * If possible, transitions to the current route's section (by expanding or | 121 * If possible, transitions to the current route's section (by expanding or |
| 118 * scrolling to it). If another transition is running, finishes or cancels | 122 * scrolling to it). If another transition is running, finishes or cancels |
| 119 * that one, then schedules this function again. This ensures the current | 123 * that one, then schedules this function again. This ensures the current |
| 120 * section is quickly shown, without getting the page into a broken state -- | 124 * section is quickly shown, without getting the page into a broken state -- |
| 121 * if currentRoute changes in between calls, just transition to the new route. | 125 * if currentRoute changes in between calls, just transition to the new route. |
| 122 * @param {boolean} scrollToSection | 126 * @param {boolean} scrollToSection |
| 127 * @param {boolean=} immediate Whether to instantly expand instead of animate. | |
| 123 * @private | 128 * @private |
| 124 */ | 129 */ |
| 125 tryTransitionToSection_: function(scrollToSection) { | 130 tryTransitionToSection_: function(scrollToSection, immediate) { |
| 126 var currentRoute = settings.getCurrentRoute(); | 131 var currentRoute = settings.getCurrentRoute(); |
| 127 var currentSection = this.getSection(currentRoute.section); | 132 var currentSection = this.getSection(currentRoute.section); |
| 128 | 133 |
| 129 // If an animation is already playing, try finishing or canceling it. | 134 // If an animation is already playing, try finishing or canceling it. |
| 130 if (this.currentAnimation_) { | 135 if (this.currentAnimation_) { |
| 131 this.maybeStopCurrentAnimation_(); | 136 this.maybeStopCurrentAnimation_(); |
| 132 // Either way, this function will be called again once the current | 137 // Either way, this function will be called again once the current |
| 133 // animation ends. | 138 // animation ends. |
| 134 return; | 139 return; |
| 135 } | 140 } |
| 136 | 141 |
| 137 var promise; | 142 var promise; |
| 138 var expandedSection = /** @type {?SettingsSectionElement} */( | 143 var expandedSection = /** @type {?SettingsSectionElement} */( |
| 139 this.$$('settings-section.expanded')); | 144 this.$$('settings-section.expanded')); |
| 140 if (expandedSection) { | 145 if (expandedSection) { |
| 141 // If the section shouldn't be expanded, collapse it. | 146 // If the section shouldn't be expanded, collapse it. |
| 142 if (!currentRoute.isSubpage() || expandedSection != currentSection) { | 147 if (!currentRoute.isSubpage() || expandedSection != currentSection) { |
| 143 promise = this.collapseSection_(expandedSection); | 148 promise = this.collapseSection_(expandedSection); |
| 144 } else { | 149 } else { |
| 145 // Scroll to top while sliding to another subpage. | 150 // Scroll to top while sliding to another subpage. |
| 146 this.scroller.scrollTop = 0; | 151 this.scroller.scrollTop = 0; |
| 147 } | 152 } |
| 148 } else if (currentSection) { | 153 } else if (currentSection) { |
| 149 // Expand the section into a subpage or scroll to it on the main page. | 154 // Expand the section into a subpage or scroll to it on the main page. |
| 150 if (currentRoute.isSubpage()) | 155 if (currentRoute.isSubpage()) |
| 151 promise = this.expandSection_(currentSection); | 156 if (immediate) |
| 157 this.expandSectionImmediate_(currentSection); | |
|
michaelpg
2017/05/24 21:29:40
maybe we should [only?] fire show-container after
scottchen
2017/05/25 19:28:30
Acknowledged. The new logic in currentRouteChanged
| |
| 158 else | |
| 159 promise = this.expandSection_(currentSection); | |
| 152 else if (scrollToSection) | 160 else if (scrollToSection) |
| 153 currentSection.scrollIntoView(); | 161 currentSection.scrollIntoView(); |
| 154 } else if ( | 162 } else if ( |
| 155 this.tagName == 'SETTINGS-BASIC-PAGE' && | 163 this.tagName == 'SETTINGS-BASIC-PAGE' && |
| 156 settings.Route.ADVANCED.contains(currentRoute) && | 164 settings.Route.ADVANCED.contains(currentRoute) && |
| 157 // Need to exclude routes that correspond to 'non-sectioned' children of | 165 // Need to exclude routes that correspond to 'non-sectioned' children of |
| 158 // ADVANCED, otherwise tryTransitionToSection_ will recurse endlessly. | 166 // ADVANCED, otherwise tryTransitionToSection_ will recurse endlessly. |
| 159 !currentRoute.isNavigableDialog) { | 167 !currentRoute.isNavigableDialog) { |
| 160 assert(currentRoute.section); | 168 assert(currentRoute.section); |
| 169 // Hide the container again while Advanecd Page template is being loaded. | |
|
michaelpg
2017/05/24 21:29:40
Advanced
scottchen
2017/05/25 19:28:30
Done.
| |
| 170 this.fire('hide-container'); | |
|
michaelpg
2017/05/24 21:29:40
does this work under both edge cases?
1. immediat
scottchen
2017/05/25 19:28:30
I tried:
1. going to basic page -> click advanced
| |
| 161 promise = this.$$('#advancedPageTemplate').get(); | 171 promise = this.$$('#advancedPageTemplate').get(); |
| 162 } | 172 } |
| 163 | 173 |
| 164 // When this animation ends, another may be necessary. Call this function | 174 // When this animation ends, another may be necessary. Call this function |
| 165 // again after the promise resolves. | 175 // again after the promise resolves. |
| 166 if (promise) | 176 if (promise) { |
| 167 promise.then(this.tryTransitionToSection_.bind(this, scrollToSection)); | 177 promise.then(this.tryTransitionToSection_.bind(this, scrollToSection)) |
| 178 .then(function() { | |
| 179 this.fire('show-container'); | |
|
michaelpg
2017/05/24 21:29:40
Do we need this both here *and* in the setTimeout
scottchen
2017/05/25 19:28:30
This is to re-show the container after hiding it o
| |
| 180 }.bind(this)); | |
| 181 } | |
| 168 }, | 182 }, |
| 169 | 183 |
| 170 /** | 184 /** |
| 171 * If the current animation is inconsistent with the current route, stops the | 185 * If the current animation is inconsistent with the current route, stops the |
| 172 * animation by finishing or canceling it so the new route can be animated to. | 186 * animation by finishing or canceling it so the new route can be animated to. |
| 173 * @private | 187 * @private |
| 174 */ | 188 */ |
| 175 maybeStopCurrentAnimation_: function() { | 189 maybeStopCurrentAnimation_: function() { |
| 176 var currentRoute = settings.getCurrentRoute(); | 190 var currentRoute = settings.getCurrentRoute(); |
| 177 var animatingSection = /** @type {?SettingsSectionElement} */( | 191 var animatingSection = /** @type {?SettingsSectionElement} */( |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 199 this.currentAnimation_.cancel(); | 213 this.currentAnimation_.cancel(); |
| 200 return; | 214 return; |
| 201 } | 215 } |
| 202 | 216 |
| 203 // The current route is a subpage, so that section needs to expand. | 217 // The current route is a subpage, so that section needs to expand. |
| 204 // Immediately finish the current collapse animation so that can happen. | 218 // Immediately finish the current collapse animation so that can happen. |
| 205 this.currentAnimation_.finish(); | 219 this.currentAnimation_.finish(); |
| 206 }, | 220 }, |
| 207 | 221 |
| 208 /** | 222 /** |
| 223 * Immediately expand the card in |section| to fill the page. | |
| 224 * @param {!SettingsSectionElement} section | |
| 225 * @private | |
| 226 */ | |
| 227 expandSectionImmediate_: function(section) { | |
| 228 assert(this.scroller); | |
| 229 section.immediateExpand(this.scroller); | |
| 230 this.finishedExpanding_(section); | |
| 231 // TODO(scottchen): iron-list inside subpages need this to render correctly. | |
| 232 this.fire('resize'); | |
| 233 }, | |
| 234 | |
| 235 /** | |
| 209 * Animates the card in |section|, expanding it to fill the page. | 236 * Animates the card in |section|, expanding it to fill the page. |
| 210 * @param {!SettingsSectionElement} section | 237 * @param {!SettingsSectionElement} section |
| 211 * @return {!Promise} Resolved when the transition is finished or canceled. | 238 * @return {!Promise} Resolved when the transition is finished or canceled. |
| 212 * @private | 239 * @private |
| 213 */ | 240 */ |
| 214 expandSection_: function(section) { | 241 expandSection_: function(section) { |
| 215 assert(this.scroller); | 242 assert(this.scroller); |
| 216 | |
| 217 if (!section.canAnimateExpand()) { | 243 if (!section.canAnimateExpand()) { |
| 218 // Try to wait for the section to be created. | 244 // Try to wait for the section to be created. |
| 219 return new Promise(function(resolve, reject) { | 245 return new Promise(function(resolve, reject) { |
| 220 setTimeout(resolve); | 246 setTimeout(resolve); |
| 221 }); | 247 }); |
| 222 } | 248 } |
| 223 | 249 |
| 224 // Save the scroller position before freezing it. | 250 // Save the scroller position before freezing it. |
| 225 this.origScrollTop_ = this.scroller.scrollTop; | 251 this.origScrollTop_ = this.scroller.scrollTop; |
| 226 this.fire('freeze-scroll', true); | 252 this.fire('freeze-scroll', true); |
| 227 | 253 |
| 228 // Freeze the section's height so its card can be removed from the flow. | 254 // Freeze the section's height so its card can be removed from the flow. |
| 229 section.setFrozen(true); | 255 section.setFrozen(true); |
| 230 | 256 |
| 231 this.currentAnimation_ = section.animateExpand(this.scroller); | 257 this.currentAnimation_ = section.animateExpand(this.scroller); |
| 232 | 258 |
| 233 var finished; | 259 return this.currentAnimation_.finished |
| 234 return this.currentAnimation_.finished.then(function() { | 260 .then( |
| 235 // Hide other sections and scroll to the top of the subpage. | 261 function() { |
| 236 this.classList.add('showing-subpage'); | 262 this.finishedExpanding_(section); |
| 237 this.toggleOtherSectionsHidden_(section.section, true); | 263 }.bind(this), |
| 238 this.scroller.scrollTop = 0; | 264 function() { |
| 239 section.setFrozen(false); | 265 // The animation was canceled; restore the section and scroll |
| 266 // position. | |
| 267 section.setFrozen(false); | |
| 268 this.scroller.scrollTop = this.origScrollTop_; | |
| 269 }.bind(this)) | |
| 270 .then(function() { | |
| 271 this.fire('freeze-scroll', false); | |
| 272 this.currentAnimation_ = null; | |
| 273 }.bind(this)); | |
| 274 }, | |
| 240 | 275 |
| 241 // Notify that the page is fully expanded. | 276 /** @private */ |
| 242 this.fire('subpage-expand'); | 277 finishedExpanding_: function(section) { |
| 278 // Hide other sections and scroll to the top of the subpage. | |
| 279 this.classList.add('showing-subpage'); | |
| 280 this.toggleOtherSectionsHidden_(section.section, true); | |
| 281 this.scroller.scrollTop = 0; | |
| 282 section.setFrozen(false); | |
| 243 | 283 |
| 244 finished = true; | 284 // Notify that the page is fully expanded. |
| 245 }.bind(this), function() { | 285 this.fire('subpage-expand'); |
| 246 // The animation was canceled; restore the section and scroll position. | |
| 247 section.setFrozen(false); | |
| 248 this.scroller.scrollTop = this.origScrollTop_; | |
| 249 | |
| 250 finished = false; | |
| 251 }.bind(this)).then(function() { | |
| 252 this.fire('freeze-scroll', false); | |
| 253 this.currentAnimation_ = null; | |
| 254 }.bind(this)); | |
| 255 }, | 286 }, |
| 256 | 287 |
| 257 /** | 288 /** |
| 258 * Animates the card in |section|, collapsing it back into its section. | 289 * Animates the card in |section|, collapsing it back into its section. |
| 259 * @param {!SettingsSectionElement} section | 290 * @param {!SettingsSectionElement} section |
| 260 * @return {!Promise} Resolved when the transition is finished or canceled. | 291 * @return {!Promise} Resolved when the transition is finished or canceled. |
| 261 */ | 292 */ |
| 262 collapseSection_: function(section) { | 293 collapseSection_: function(section) { |
| 263 assert(this.scroller); | 294 assert(this.scroller); |
| 264 assert(section.classList.contains('expanded')); | 295 assert(section.classList.contains('expanded')); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 349 return /** @type {?SettingsSectionElement} */( | 380 return /** @type {?SettingsSectionElement} */( |
| 350 this.$$('settings-section[section="' + section + '"]')); | 381 this.$$('settings-section[section="' + section + '"]')); |
| 351 }, | 382 }, |
| 352 }; | 383 }; |
| 353 | 384 |
| 354 /** @polymerBehavior */ | 385 /** @polymerBehavior */ |
| 355 var MainPageBehavior = [ | 386 var MainPageBehavior = [ |
| 356 settings.RouteObserverBehavior, | 387 settings.RouteObserverBehavior, |
| 357 MainPageBehaviorImpl, | 388 MainPageBehaviorImpl, |
| 358 ]; | 389 ]; |
| OLD | NEW |