diff --git a/docs/src-pwa/register-service-worker.js b/docs/src-pwa/register-service-worker.js index 39019e56cf9b..f3b3d3dedac2 100644 --- a/docs/src-pwa/register-service-worker.js +++ b/docs/src-pwa/register-service-worker.js @@ -1,5 +1,5 @@ import { register } from 'register-service-worker' -import { Notify } from 'quasar' +import { Notify, SessionStorage } from 'quasar' import { mdiCached } from '@quasar/extras/mdi-v6' // The ready(), registered(), cached(), updatefound() and updated() @@ -31,24 +31,30 @@ register(process.env.SERVICE_WORKER_FILE, { updated (/* registration */) { Notify.create({ - color: 'negative', - icon: mdiCached, - message: 'Updated content is available. Please refresh the page.', + classes: 'shadow-10 no-border-radius q-px-md q-pb-md', + color: 'white', + textColor: 'dark', + message: 'New content is available', timeout: 0, multiLine: true, - position: 'top', + position: 'bottom', actions: [ { + icon: mdiCached, label: 'Refresh', - color: 'yellow', + class: 'bg-deep-orange-2 full-width no-border-radius', + color: 'dark', + padding: 'xs', + noCaps: true, + flat: false, + outline: true, handler: () => { + const scrollingElement = document.scrollingElement || document.documentElement + + SessionStorage.set('restoreScroll', [ scrollingElement.scrollTop, scrollingElement.scrollLeft ]) + window.location.reload() } - }, - { - label: 'Dismiss', - color: 'white', - handler: () => {} } ] }) diff --git a/docs/src/layouts/DocLayout.vue b/docs/src/layouts/DocLayout.vue index 3f163f076a1d..5c34c9d0a9e3 100644 --- a/docs/src/layouts/DocLayout.vue +++ b/docs/src/layouts/DocLayout.vue @@ -125,7 +125,7 @@ q-layout.doc-layout(view="lHh LpR lff", @scroll="onScroll") q-item-section {{ tocItem.title }} q-page-container - router-view + router-view(@hook:mounted="onPageMounted") q-page-scroller q-btn(fab-mini, color="brand-primary", glossy, :icon="mdiChevronUp") @@ -143,7 +143,7 @@ import AppSearchResults from 'components/AppSearchResults' import LayoutSearchMixin from './layout-search-mixin' -const { setScrollPosition, getScrollPosition } = scroll +const { setScrollPosition, getScrollPosition, executeWhenScrollable } = scroll export default { name: 'Layout', @@ -204,9 +204,13 @@ export default { watch: { $route (newRoute, oldRoute) { this.leftDrawerState = this.$q.screen.width > 1023 - setTimeout(() => { - this.scrollToCurrentAnchor(newRoute.path !== oldRoute.path) - }) + + if (newRoute.path === oldRoute.path) { + this.resetScrollQueue() + this.removeScrollFn = executeWhenScrollable(() => { + this.scrollToCurrentAnchor() + }) + } }, hasRightDrawer (shown) { @@ -241,17 +245,11 @@ export default { }, scrollTo (id) { - clearTimeout(this.scrollTimer) - - if (this.rightDrawerOnLayout !== true) { - this.rightDrawerState = false - this.scrollTimer = setTimeout(() => { - this.changeRouterHash('#' + id) - }, 300) - } - else { + this.resetScrollQueue() + this.rightDrawerOnLayout !== true && (this.rightDrawerState = false) + this.removeScrollFn = executeWhenScrollable(() => { this.changeRouterHash('#' + id) - } + }) }, scrollPage (el, delay) { @@ -327,13 +325,15 @@ export default { anchorEl = anchorEl.parentElement } - document.body.classList.add('q-scroll--lock') - anchorEl.classList.add('q-scroll--anchor') + if (anchorEl) { + document.body.classList.add('q-scroll--lock') + anchorEl.classList.add('q-scroll--anchor') - setTimeout(() => { - document.body.classList.remove('q-scroll--lock') - anchorEl && anchorEl.classList.remove('q-scroll--anchor') - }, 2000) + setTimeout(() => { + document.body.classList.remove('q-scroll--lock') + anchorEl && anchorEl.classList.remove('q-scroll--anchor') + }, 2000) + } } this.scrollPage(el, immediate === true ? 0 : 500) @@ -342,15 +342,48 @@ export default { this.preventTocUpdate = false this.updateActiveToc() } + }, + + resetScrollQueue () { + clearTimeout(this.scrollTimer) + if (this.removeScrollFn !== void 0) { + this.removeScrollFn() + this.removeScrollFn = void 0 + } + }, + + onPageMounted () { + clearTimeout(this.scrollTimer) + this.scrollTimer = setTimeout(() => { + this.resetScrollQueue() + this.removeScrollFn = executeWhenScrollable(() => { + if (this.restoreScroll !== void 0) { + const scrollingElement = document.scrollingElement || document.documentElement + + scrollingElement.scrollTop = this.restoreScroll[0] + scrollingElement.scrollLeft = this.restoreScroll[1] + + this.restoreScroll = void 0 + } + else { + this.scrollToCurrentAnchor(true) + } + }) + }) } }, mounted () { - this.scrollToCurrentAnchor(true) + const restoreScroll = this.$q.sessionStorage.getItem('restoreScroll') + this.$q.sessionStorage.remove('restoreScroll') + + if (Array.isArray(restoreScroll) === true && restoreScroll.length === 2) { + this.restoreScroll = restoreScroll + } }, beforeDestroy () { - clearTimeout(this.scrollTimer) + this.resetScrollQueue() } } diff --git a/docs/src/router/index.js b/docs/src/router/index.js index 0a2c7668c0e6..8eefe1b419e3 100644 --- a/docs/src/router/index.js +++ b/docs/src/router/index.js @@ -1,10 +1,14 @@ import Vue from 'vue' import VueRouter from 'vue-router' +import { scroll } from 'quasar' import routes from './routes' Vue.use(VueRouter) +const { executeWhenScrollable } = scroll +let removeScrollFn + /* * If not building with SSR mode, you can * directly export the Router instantiation @@ -15,11 +19,16 @@ export default function () { routes, scrollBehavior (to, _, savedPosition) { - if (to.hash.length > 1) { - return false - } - - return savedPosition || { x: 0, y: 0 } + return new Promise(resolve => { + removeScrollFn && removeScrollFn() + removeScrollFn = executeWhenScrollable(() => { + resolve( + to.hash.length > 1 + ? false + : savedPosition || { x: 0, y: 0 } + ) + }) + }) }, // Leave these as is and change from quasar.conf.js instead!