Refactored search lock

This commit is contained in:
squidfunk
2020-02-17 11:35:36 +01:00
parent 2c0177ab56
commit 95c66b99e3
2 changed files with 59 additions and 39 deletions

View File

@@ -45,3 +45,33 @@ export function resetOverflowScrolling(
): void { ): void {
el.style.webkitOverflowScrolling = "" el.style.webkitOverflowScrolling = ""
} }
/* ------------------------------------------------------------------------- */
/**
* Set scroll lock
*
* @param el - Scrollable element
* @param value - Vertical offset
*/
export function setScrollLock(
el: HTMLElement, value: number
): void {
el.setAttribute("data-md-state", "lock")
el.style.top = `-${value}px`
}
/**
* Reset scroll lock
*
* @param el - Scrollable element
*/
export function resetScrollLock(
el: HTMLElement
): void {
const value = -1 * parseInt(el.style.top, 10)
el.removeAttribute("data-md-state")
el.style.top = ""
if (value)
window.scrollTo(0, value)
}

View File

@@ -32,7 +32,8 @@ import {
merge, merge,
of, of,
NEVER, NEVER,
combineLatest combineLatest,
animationFrameScheduler
} from "rxjs" } from "rxjs"
import { import {
delay, delay,
@@ -45,7 +46,8 @@ import {
bufferCount, bufferCount,
startWith, startWith,
pluck, pluck,
withLatestFrom withLatestFrom,
observeOn
} from "rxjs/operators" } from "rxjs/operators"
import { import {
@@ -67,7 +69,7 @@ import {
import { setupSearchWorker } from "./workers" import { setupSearchWorker } from "./workers"
import { renderSource } from "templates" import { renderSource } from "templates"
import { fetchGitHubStats } from "integrations/source/github" import { fetchGitHubStats } from "integrations/source/github"
import { setToggle } from "actions" import { setToggle, setScrollLock, resetScrollLock } from "actions"
import { import {
Component, Component,
mountHeader, mountHeader,
@@ -83,6 +85,7 @@ import {
import { mountClipboard } from "./integrations/clipboard" import { mountClipboard } from "./integrations/clipboard"
import { patchTables, patchDetails } from "patches" import { patchTables, patchDetails } from "patches"
import { takeIf, not, isConfig } from "utilities" import { takeIf, not, isConfig } from "utilities"
import { setSearchLock } from "actions/search/_"
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@@ -306,6 +309,29 @@ export function initialize(config: unknown) {
) )
.subscribe() .subscribe()
// scroll lock
const toggle$ = useToggle("search")
combineLatest([
toggle$.pipe(switchMap(watchToggle)),
tablet$,
])
.pipe(
withLatestFrom(viewport$),
switchMap(([[toggle, tablet], { offset: { y }}]) => {
const active = toggle && !tablet
return of(document.body)
.pipe(
delay(active ? 400 : 100),
observeOn(animationFrameScheduler),
tap(el => active
? setScrollLock(el, y)
: resetScrollLock(el)
)
)
})
)
.subscribe()
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
// watchClipboard // watchClipboard
@@ -332,42 +358,6 @@ export function initialize(config: unknown) {
patchDetails({ document$ }) patchDetails({ document$ })
.subscribe() .subscribe()
// scroll lock
let scroll = 0
combineLatest([
useToggle("search")
.pipe(
switchMap(watchToggle)
),
tablet$,
]).pipe(
tap(([toggle, tablet]) => {
if (toggle && !tablet) {
scroll = scrollY
setTimeout(() => {
requestAnimationFrame(() => {
document.body.style.position = 'fixed';
document.body.style.top = `-${scroll}px`;
// data.mdState = lock
})
}, 400)
} else {
/* Scroll to former position, but wait for 100ms to prevent flashes on
iOS. A short timeout seems to do the trick */
setTimeout(() => {
requestAnimationFrame(() => {
document.body.style.position = '';
document.body.style.top = '';
if (scroll)
window.scrollTo(0, scroll)
})
}, 100)
}
})
)
.subscribe()
/* Force 1px scroll offset to trigger overflow scrolling */ /* Force 1px scroll offset to trigger overflow scrolling */
if (true || navigator.userAgent.match(/(iPad|iPhone|iPod)/g)) { if (true || navigator.userAgent.match(/(iPad|iPhone|iPod)/g)) {
const scrollable = document.querySelectorAll("[data-md-scrollfix]") const scrollable = document.querySelectorAll("[data-md-scrollfix]")