Improved flow of observables/emissions

This commit is contained in:
squidfunk 2020-03-16 14:59:59 +01:00
parent 47aa47ee4c
commit 653d535a22
16 changed files with 86 additions and 93 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,10 @@
{ {
"assets/javascripts/bundle.js": "assets/javascripts/bundle.5a96f0ab.min.js", "assets/javascripts/bundle.js": "assets/javascripts/bundle.bdb82690.min.js",
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.5a96f0ab.min.js.map", "assets/javascripts/bundle.js.map": "assets/javascripts/bundle.bdb82690.min.js.map",
"assets/javascripts/vendor.js": "assets/javascripts/vendor.daf35bb7.min.js", "assets/javascripts/vendor.js": "assets/javascripts/vendor.aad0415a.min.js",
"assets/javascripts/vendor.js.map": "assets/javascripts/vendor.daf35bb7.min.js.map", "assets/javascripts/vendor.js.map": "assets/javascripts/vendor.aad0415a.min.js.map",
"assets/javascripts/worker/search.js": "assets/javascripts/worker/search.784c5235.min.js", "assets/javascripts/worker/search.js": "assets/javascripts/worker/search.784c5235.min.js",
"assets/javascripts/worker/search.js.map": "assets/javascripts/worker/search.784c5235.min.js.map", "assets/javascripts/worker/search.js.map": "assets/javascripts/worker/search.784c5235.min.js.map",
"assets/stylesheets/main.css": "assets/stylesheets/main.1f420948.min.css", "assets/stylesheets/main.css": "assets/stylesheets/main.acbb280a.min.css",
"assets/stylesheets/palette.css": "assets/stylesheets/palette.31180ff2.min.css" "assets/stylesheets/palette.css": "assets/stylesheets/palette.31180ff2.min.css"
} }

View File

@ -41,7 +41,7 @@
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block styles %} {% block styles %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.1f420948.min.css' | url }}"> <link rel="stylesheet" href="{{ 'assets/stylesheets/main.acbb280a.min.css' | url }}">
{% if palette.primary or palette.accent %} {% if palette.primary or palette.accent %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/palette.31180ff2.min.css' | url }}"> <link rel="stylesheet" href="{{ 'assets/stylesheets/palette.31180ff2.min.css' | url }}">
{% endif %} {% endif %}
@ -177,8 +177,8 @@
<script>var __config={}</script> <script>var __config={}</script>
{% endblock %} {% endblock %}
{% block scripts %} {% block scripts %}
<script src="{{ 'assets/javascripts/vendor.daf35bb7.min.js' | url }}"></script> <script src="{{ 'assets/javascripts/vendor.aad0415a.min.js' | url }}"></script>
<script src="{{ 'assets/javascripts/bundle.5a96f0ab.min.js' | url }}"></script> <script src="{{ 'assets/javascripts/bundle.bdb82690.min.js' | url }}"></script>
{%- set translations = {} -%} {%- set translations = {} -%}
{%- for key in [ {%- for key in [
"clipboard.copy", "clipboard.copy",

View File

@ -93,9 +93,11 @@ export function watchViewport(): Observable<Viewport> {
export function watchViewportAt( export function watchViewportAt(
el: HTMLElement, { header$, viewport$ }: WatchAtOptions el: HTMLElement, { header$, viewport$ }: WatchAtOptions
): Observable<Viewport> { ): Observable<Viewport> {
const offset$ = viewport$ const offset$ = combineLatest([
viewport$.pipe(distinctUntilKeyChanged("size")),
header$
])
.pipe( .pipe(
distinctUntilKeyChanged("size"),
map((): ViewportOffset => ({ map((): ViewportOffset => ({
x: el.offsetLeft, x: el.offsetLeft,
y: el.offsetTop y: el.offsetTop

View File

@ -92,7 +92,7 @@ export function mountHeader(
): OperatorFunction<HTMLElement, Header> { ): OperatorFunction<HTMLElement, Header> {
return pipe( return pipe(
switchMap(el => { switchMap(el => {
const header$ = watchHeader(el, { viewport$ }) const header$ = watchHeader(el)
/* Compute whether the header should switch to page header */ /* Compute whether the header should switch to page header */
const type$ = useComponent("main") const type$ = useComponent("main")

View File

@ -28,14 +28,14 @@ import {
pipe pipe
} from "rxjs" } from "rxjs"
import { import {
distinctUntilKeyChanged,
finalize, finalize,
map,
observeOn, observeOn,
switchMap, shareReplay,
tap tap
} from "rxjs/operators" } from "rxjs/operators"
import { Viewport } from "browser" import { watchElementSize } from "browser"
import { Header, HeaderType } from "../_" import { Header, HeaderType } from "../_"
import { import {
@ -43,17 +43,6 @@ import {
setHeaderTitleActive setHeaderTitleActive
} from "../set" } from "../set"
/* ----------------------------------------------------------------------------
* Helper types
* ------------------------------------------------------------------------- */
/**
* Watch options
*/
interface WatchOptions {
viewport$: Observable<Viewport> /* Viewport observable */
}
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* Functions * Functions
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
@ -61,32 +50,32 @@ interface WatchOptions {
/** /**
* Watch header * Watch header
* *
* The header is wrapped in an observable to pave the way for auto-hiding or
* other dynamic behaviors that may be implemented later on.
*
* @param el - Header element * @param el - Header element
* @param options - Options
* *
* @return Header observable * @return Header observable
*/ */
export function watchHeader( export function watchHeader(
el: HTMLElement, { viewport$ }: WatchOptions el: HTMLElement
): Observable<Omit<Header, "type">> { ): Observable<Omit<Header, "type">> {
return viewport$ const styles = getComputedStyle(el)
.pipe( if ([
distinctUntilKeyChanged("size"), "sticky", /* Modern browsers */
switchMap(() => { "-webkit-sticky" /* Safari */
const styles = getComputedStyle(el) ].includes(styles.position)) {
const sticky = [ return watchElementSize(el)
"sticky", /* Modern browsers */ .pipe(
"-webkit-sticky" /* Safari */ map(({ height }) => ({
].includes(styles.position) sticky: true,
return of({ height
sticky, })),
height: sticky ? el.offsetHeight : 0 shareReplay(1)
}) )
}) } else {
) return of({
sticky: false,
height: 0
})
}
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */

View File

@ -29,11 +29,13 @@ import {
} from "rxjs" } from "rxjs"
import { import {
distinctUntilChanged, distinctUntilChanged,
distinctUntilKeyChanged,
finalize, finalize,
map, map,
observeOn, observeOn,
pluck, pluck,
shareReplay, shareReplay,
switchMap,
tap tap
} from "rxjs/operators" } from "rxjs/operators"
@ -81,17 +83,23 @@ export function watchMain(
/* Compute necessary adjustment for header */ /* Compute necessary adjustment for header */
const adjust$ = header$ const adjust$ = header$
.pipe( .pipe(
pluck("height") pluck("height"),
distinctUntilChanged(),
shareReplay(1)
) )
/* Compute the main area's top and bottom markers */ /* Compute the main area's top and bottom markers */
const marker$ = watchElementSize(el) const marker$ = adjust$
.pipe( .pipe(
map(({ height }) => ({ switchMap(() => watchElementSize(el)
top: el.offsetTop, .pipe(
bottom: el.offsetTop + height map(({ height }) => ({
})), top: el.offsetTop,
distinctUntilChanged(), bottom: el.offsetTop + height
}))
)
),
distinctUntilKeyChanged("top"),
shareReplay(1) shareReplay(1)
) )

View File

@ -25,7 +25,6 @@ import {
Observable, Observable,
animationFrameScheduler, animationFrameScheduler,
combineLatest, combineLatest,
of,
pipe pipe
} from "rxjs" } from "rxjs"
import { import {
@ -90,15 +89,13 @@ interface ApplyOptions {
export function watchSidebar( export function watchSidebar(
el: HTMLElement, { main$, viewport$ }: WatchOptions el: HTMLElement, { main$, viewport$ }: WatchOptions
): Observable<Sidebar> { ): Observable<Sidebar> {
const inner = el.parentElement! const adjust = el.parentElement!.offsetTop
const outer = inner.parentElement! - el.parentElement!.parentElement!.offsetTop
/* Compute the sidebar's available height */ /* Compute the sidebar's available height */
const adjust$ = of(inner.offsetTop - outer.offsetTop) const height$ = combineLatest([main$, viewport$])
const height$ = viewport$
.pipe( .pipe(
withLatestFrom(adjust$, main$), map(([{ offset, height }, { offset: { y } }]) => (
map(([{ offset: { y } }, adjust, { offset, height }]) => (
height height
+ Math.min(adjust, Math.max(0, y - offset)) + Math.min(adjust, Math.max(0, y - offset))
- adjust - adjust
@ -107,12 +104,9 @@ export function watchSidebar(
) )
/* Compute whether the sidebar should be locked */ /* Compute whether the sidebar should be locked */
const lock$ = viewport$ const lock$ = combineLatest([main$, viewport$])
.pipe( .pipe(
withLatestFrom(adjust$, main$), map(([{ offset }, { offset: { y } }]) => y >= offset + adjust),
map(([{ offset: { y } }, adjust, { offset }]) => (
y >= offset + adjust
)),
distinctUntilChanged() distinctUntilChanged()
) )