From 74b02ad3824f42311d927cf79813549e9c6d7d95 Mon Sep 17 00:00:00 2001 From: squidfunk Date: Wed, 19 Feb 2020 10:18:33 +0100 Subject: [PATCH] Refactored cache observable factory and documented utilities --- .../observables/agent/element/_/index.ts | 2 +- .../javascripts/patches/details/index.ts | 2 +- .../javascripts/utilities/rxjs/_/index.ts | 43 +++++++++++-------- .../utilities/rxjs/operators/index.ts | 3 ++ .../javascripts/utilities/string/index.ts | 19 +++++--- 5 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/assets/javascripts/observables/agent/element/_/index.ts b/src/assets/javascripts/observables/agent/element/_/index.ts index c0fedac50..cfa517f97 100644 --- a/src/assets/javascripts/observables/agent/element/_/index.ts +++ b/src/assets/javascripts/observables/agent/element/_/index.ts @@ -56,7 +56,7 @@ export function getElementOrThrow( const el = getElement(selector, node) if (typeof el === "undefined") throw new ReferenceError( - `Missing element: expected "${selector}" to match an element` + `Missing element: expected "${selector}" to be present` ) return el } diff --git a/src/assets/javascripts/patches/details/index.ts b/src/assets/javascripts/patches/details/index.ts index d25b1a0b1..67c191b98 100644 --- a/src/assets/javascripts/patches/details/index.ts +++ b/src/assets/javascripts/patches/details/index.ts @@ -85,7 +85,7 @@ export function patchDetails( el.setAttribute("open", "") }) - /* Open details before anchor jump */ + /* Open parent details before anchor jump */ merge(hash$, of(location.hash)) .pipe( filter(hash => !!hash.length), diff --git a/src/assets/javascripts/utilities/rxjs/_/index.ts b/src/assets/javascripts/utilities/rxjs/_/index.ts index 808ce266a..b9111ec61 100644 --- a/src/assets/javascripts/utilities/rxjs/_/index.ts +++ b/src/assets/javascripts/utilities/rxjs/_/index.ts @@ -20,7 +20,7 @@ * IN THE SOFTWARE. */ -import { Observable, of } from "rxjs" +import { Observable, defer, of } from "rxjs" import { map } from "rxjs/operators" /* ---------------------------------------------------------------------------- @@ -46,7 +46,10 @@ export function not( /** * Cache the last value emitted by an observable in session storage * - * Note that the value must be serializable as `JSON`. + * If the key is not found in session storage, the factory is executed and the + * latest value emitted will automatically be persisted to sessions storage. + * Note that the values emitted by the returned observable must be serializable + * as `JSON`, or data will be lost. * * @template T - Value type * @@ -58,23 +61,25 @@ export function not( export function cache( key: string, factory: () => Observable ): Observable { - const data = sessionStorage.getItem(key) - if (data) { - return of(JSON.parse(data) as T) + return defer(() => { + const data = sessionStorage.getItem(key) + if (data) { + return of(JSON.parse(data) as T) - /* Retrieve value from observable factory and write to storage */ - } else { - const value$ = factory() - value$ - .subscribe(value => { - try { - sessionStorage.setItem(key, JSON.stringify(value)) - } catch (err) { - /* Just swallow */ - } - }) + /* Retrieve value from observable factory and write to storage */ + } else { + const value$ = factory() + value$ + .subscribe(value => { + try { + sessionStorage.setItem(key, JSON.stringify(value)) + } catch (err) { + /* Uncritical, just swallow */ + } + }) - /* Return value observable */ - return value$ - } + /* Return value observable */ + return value$ + } + }) } diff --git a/src/assets/javascripts/utilities/rxjs/operators/index.ts b/src/assets/javascripts/utilities/rxjs/operators/index.ts index c1287df4a..e302306df 100644 --- a/src/assets/javascripts/utilities/rxjs/operators/index.ts +++ b/src/assets/javascripts/utilities/rxjs/operators/index.ts @@ -30,6 +30,9 @@ import { filter, map, withLatestFrom } from "rxjs/operators" /** * Toggle emission with another observable * + * While this could also be implemented using window operators, it may lead to + * an unnecessary increase in bundle size, so we use operators we use anyway. + * * @template T - Value type * * @param toggle$ - Toggle observable diff --git a/src/assets/javascripts/utilities/string/index.ts b/src/assets/javascripts/utilities/string/index.ts index 4a610d748..5c93925ea 100644 --- a/src/assets/javascripts/utilities/string/index.ts +++ b/src/assets/javascripts/utilities/string/index.ts @@ -82,7 +82,14 @@ export function truncate(value: string, n: number): string { * Round a number for display with source facts * * This is a reverse engineered implementation of GitHub's weird rounding - * algorithm for stars, forks and all other numbers. Probably incorrect. + * algorithm for stars, forks and all other numbers. While all numbers below + * `1,000` are returned as-is, bigger numbers are converted to fixed numbers + * in the following way: + * + * - `1,049` => `1k` + * - `1,050` => `1,1k` + * - `1,949` => `1,9k` + * - `1,950` => `2k` * * @param value - Original value * @@ -104,13 +111,13 @@ export function round(value: number): string { * * @param value - Value to be hashed * - * @return Hash + * @return Hash as 32bit integer */ export function hash(value: string): number { - let k = 0 + let h = 0 for (let i = 0, len = value.length; i < len; i++) { - k = ((k << 5) - k) + value.charCodeAt(i) - k |= 0 // Convert to 32bit integer + h = ((h << 5) - h) + value.charCodeAt(i) + h |= 0 // Convert to 32bit integer } - return k + return h }