diff options
| author | Sam Wilkins <abdullah_ahmed@brown.edu> | 2019-05-16 13:13:50 -0400 | 
|---|---|---|
| committer | Sam Wilkins <abdullah_ahmed@brown.edu> | 2019-05-16 13:13:50 -0400 | 
| commit | 4dacd1220e6a0ef73167f187f52f3b4c222c2586 (patch) | |
| tree | 12d481d4d421fda6bd4490af4d0b5d77c6c1131c /src/client/util/History.ts | |
| parent | 3451ce40cbd488cede7d29b6e39594f740e366b5 (diff) | |
| parent | 53351f6c5b448b93f2865eb38868bddb95ec4c1d (diff) | |
pulled from master and resolved
Diffstat (limited to 'src/client/util/History.ts')
| -rw-r--r-- | src/client/util/History.ts | 122 | 
1 files changed, 122 insertions, 0 deletions
| diff --git a/src/client/util/History.ts b/src/client/util/History.ts new file mode 100644 index 000000000..92d2b2b44 --- /dev/null +++ b/src/client/util/History.ts @@ -0,0 +1,122 @@ +import { Doc, Opt, Field } from "../../new_fields/Doc"; +import { DocServer } from "../DocServer"; +import { Main } from "../views/Main"; +import { RouteStore } from "../../server/RouteStore"; + +export namespace HistoryUtil { +    export interface DocInitializerList { +        [key: string]: string | number; +    } + +    export interface DocUrl { +        type: "doc"; +        docId: string; +        initializers: { +            [docId: string]: DocInitializerList; +        }; +    } + +    export type ParsedUrl = DocUrl; + +    // const handlers: ((state: ParsedUrl | null) => void)[] = []; +    function onHistory(e: PopStateEvent) { +        if (window.location.pathname !== RouteStore.home) { +            const url = e.state as ParsedUrl || parseUrl(window.location.pathname); +            if (url) { +                switch (url.type) { +                    case "doc": +                        onDocUrl(url); +                        break; +                } +            } +        } +        // for (const handler of handlers) { +        //     handler(e.state); +        // } +    } + +    export function pushState(state: ParsedUrl) { +        history.pushState(state, "", createUrl(state)); +    } + +    export function replaceState(state: ParsedUrl) { +        history.replaceState(state, "", createUrl(state)); +    } + +    function copyState(state: ParsedUrl): ParsedUrl { +        return JSON.parse(JSON.stringify(state)); +    } + +    export function getState(): ParsedUrl { +        return copyState(history.state); +    } + +    // export function addHandler(handler: (state: ParsedUrl | null) => void) { +    //     handlers.push(handler); +    // } + +    // export function removeHandler(handler: (state: ParsedUrl | null) => void) { +    //     const index = handlers.indexOf(handler); +    //     if (index !== -1) { +    //         handlers.splice(index, 1); +    //     } +    // } + +    export function parseUrl(pathname: string): ParsedUrl | undefined { +        let pathnameSplit = pathname.split("/"); +        if (pathnameSplit.length !== 2) { +            return undefined; +        } +        const type = pathnameSplit[0]; +        const data = pathnameSplit[1]; + +        if (type === "doc") { +            const s = data.split("?"); +            if (s.length < 1 || s.length > 2) { +                return undefined; +            } +            const docId = s[0]; +            const initializers = s.length === 2 ? JSON.parse(decodeURIComponent(s[1])) : {}; +            return { +                type: "doc", +                docId, +                initializers +            }; +        } + +        return undefined; +    } + +    export function createUrl(params: ParsedUrl): string { +        let baseUrl = DocServer.prepend(`/${params.type}`); +        switch (params.type) { +            case "doc": +                const initializers = encodeURIComponent(JSON.stringify(params.initializers)); +                const id = params.docId; +                let url = baseUrl + `/${id}`; +                if (Object.keys(params.initializers).length) { +                    url += `?${initializers}`; +                } +                return url; +        } +        return ""; +    } + +    export async function initDoc(id: string, initializer: DocInitializerList) { +        const doc = await DocServer.GetRefField(id); +        if (!(doc instanceof Doc)) { +            return; +        } +        Doc.assign(doc, initializer); +    } + +    async function onDocUrl(url: DocUrl) { +        const field = await DocServer.GetRefField(url.docId); +        await Promise.all(Object.keys(url.initializers).map(id => initDoc(id, url.initializers[id]))); +        if (field instanceof Doc) { +            Main.Instance.openWorkspace(field, true); +        } +    } + +    window.onpopstate = onHistory; +} | 
