diff --git a/src/pagerouter/PageRouter.ts b/src/pagerouter/PageRouter.ts index 9ea488b..0260601 100644 --- a/src/pagerouter/PageRouter.ts +++ b/src/pagerouter/PageRouter.ts @@ -70,11 +70,11 @@ export class PageRouter { this.currentPageID = pageID; this.currentPage = await this.pageList.getPage(pageID); - await this.currentPage.setRouterAndState(this, this.state); - // Dispatch an event saying the page has been changed. this.onPageChange(); + await this.currentPage.setRouterAndState(this, this.state); + // Render the page. await this.renderPage(); } diff --git a/src/state/PageState.ts b/src/state/PageState.ts index c88a8ee..4c9bd63 100644 --- a/src/state/PageState.ts +++ b/src/state/PageState.ts @@ -4,6 +4,11 @@ export class PageState { constructor() { const params = new URLSearchParams(window.location.search); if (params.has("reset")) this.storage.clear(); + if (params.has("state")) { + console.log("state owo") + this.loadState(JSON.parse(params.get("state"))); + } + if (params.has("incognito")) { this.storage = sessionStorage; } else { @@ -13,6 +18,33 @@ export class PageState { private storage: StorageType; + dumpState(): { [key: string]: unknown } { + return { + "baseMount": this.baseMount, + "secretPath": this.secretPath, + "secretVersion": this.secretVersion, + "secretItem": this.secretItem, + "secretMountType": this.secretMountType, + "policyItem": this.policyItem, + "authPath": this.authPath, + "userPassUser": this.userPassUser, + "currentPage": this.currentPage, + } + } + + loadState(newState: { [key: string]: unknown }) { + console.log(newState) + for (let prop in newState) { + console.log("WANTS", prop) + if (prop in this) { + console.log("HAS", prop.toString()); + // @ts-ignore + this[prop] = newState[prop]; + } + } + + } + // NOTE: When a item in the page state isn't a string (e.g it is a array or object), // you need to add helper methods to mutate it or else it wont save. // example: secretPath is a array so when you try to .push() to it @@ -22,6 +54,9 @@ export class PageState { // by using a bunch of functions and modifying localStorage in order to remove some of // the clunkyness of this approach, but for now, this works. + // these are all ones that persist across browser sessions + // usually in localStorage unless in incognito. + get apiURL(): string | null { const apiurl = this.storage.getItem("apiURL") || ""; return apiurl.length > 0 ? apiurl : null; @@ -52,6 +87,10 @@ export class PageState { this.storage.setItem("language", value); } + // all of these are sessionStorage and not persisted + // so can have multiple tabs open + // TODO: move to just local variables maybe + get baseMount(): string { return sessionStorage.getItem("baseMount") || ""; } diff --git a/src/ui/elements/CopyStateLinkButton.tsx b/src/ui/elements/CopyStateLinkButton.tsx new file mode 100644 index 0000000..c259f9a --- /dev/null +++ b/src/ui/elements/CopyStateLinkButton.tsx @@ -0,0 +1,33 @@ +import { Component, JSX, createRef } from "preact"; +import { addClipboardNotifications } from "../../pageUtils"; +import ClipboardJS from "clipboard"; +import { PageState } from "../../state/PageState"; + +export type CopyStateLinkButtonProps = { + state: PageState; +}; + +export class CopyStateLinkButton extends Component { + buttonRef = createRef(); + + componentDidMount(): void { + const clipboard = new ClipboardJS(this.buttonRef.current); + addClipboardNotifications(clipboard, 600); + } + + render(): JSX.Element { + const newURL = new URL(window.location.toString()); + newURL.searchParams.set("state", JSON.stringify(this.props.state.dumpState())); + + return ( + + ); + } +} diff --git a/src/ui/pages/Secrets/SecretTitleElement.tsx b/src/ui/pages/Secrets/SecretTitleElement.tsx index c5cc5e8..82f8d47 100644 --- a/src/ui/pages/Secrets/SecretTitleElement.tsx +++ b/src/ui/pages/Secrets/SecretTitleElement.tsx @@ -1,5 +1,7 @@ import { JSX } from "preact/jsx-runtime"; import { Page } from "../../../types/Page"; +import { CopyStateLinkButton } from "../../elements/CopyStateLinkButton"; + function currentTitleSecretText(page: Page): string { let secretItemText = page.state.secretItem; @@ -61,6 +63,7 @@ export function SecretTitleElement(props: SecretTitleElementProps): JSX.Element ))} {page.state.secretItem.length != 0 && {currentTitleSecretText(page)}} {suffix.length != 0 && {suffix}} + ); }