diff --git a/frontend/src/components/profile-browser.ts b/frontend/src/components/profile-browser.ts index aa9d7e07..2a1fb48a 100644 --- a/frontend/src/components/profile-browser.ts +++ b/frontend/src/components/profile-browser.ts @@ -1,12 +1,12 @@ // import { LitElement, html } from "lit"; -import { property, state } from "lit/decorators.js"; -import { ref } from "lit/directives/ref.js"; +import { property, state, query } from "lit/decorators.js"; import { msg, localized, str } from "@lit/localize"; import type { AuthState } from "../utils/AuthService"; import LiteElement, { html } from "../utils/LiteElement"; const POLL_INTERVAL_SECONDS = 2; +const hiddenClassList = ["translate-x-2/3", "opacity-0", "pointer-events-none"]; /** * View embedded profile browser @@ -26,10 +26,6 @@ const POLL_INTERVAL_SECONDS = 2; */ @localized() export class ProfileBrowser extends LiteElement { - // TODO remove sidebar constaint once devtools panel - // is hidden on the backend - static SIDE_BAR_WIDTH = 288; - @property({ type: Object }) authState!: AuthState; @@ -57,9 +53,21 @@ export class ProfileBrowser extends LiteElement { @state() private isFullscreen = false; + @state() + private showOriginSidebar = false; + @state() private newOrigins: string[] = []; + @query("#profileBrowserSidebar") + private sidebar?: HTMLElement; + + @query("#iframeWrapper") + private iframeWrapper?: HTMLElement; + + @query("iframe") + private iframe?: HTMLIFrameElement; + private pollTimerId?: number; connectedCallback() { @@ -73,7 +81,7 @@ export class ProfileBrowser extends LiteElement { document.removeEventListener("fullscreenchange", this.onFullscreenChange); } - updated(changedProperties: Map) { + willUpdate(changedProperties: Map) { if (changedProperties.has("browserId")) { if (this.browserId) { window.clearTimeout(this.pollTimerId); @@ -85,40 +93,84 @@ export class ProfileBrowser extends LiteElement { window.clearTimeout(this.pollTimerId); } } + if ( + changedProperties.has("showOriginSidebar") && + changedProperties.get("showOriginSidebar") !== undefined + ) { + this.animateSidebar(); + } + } + + private animateSidebar() { + if (!this.sidebar) return; + if (this.showOriginSidebar) { + this.sidebar.classList.remove(...hiddenClassList); + } else { + this.sidebar.classList.add(...hiddenClassList); + } } render() { return html` -
-
+
+ ${this.renderControlBar()} +
+ ${this.renderBrowser()}
- ${this.renderBrowser()} -
-
- ${document.fullscreenEnabled ? this.renderFullscreenButton() : ""} - ${this.renderOrigins()} ${this.renderNewOrigins()} +
+ ${this.renderOrigins()} ${this.renderNewOrigins()} +
`; } + private renderControlBar() { + if (this.isFullscreen) { + return html` +
+ ${this.renderSidebarButton()} + document.exitFullscreen()} + > +
+ `; + } + + return html` +
+ ${this.renderSidebarButton()} + this.enterFullscreen("interactive-browser")} + > +
+ `; + } + private renderBrowser() { if (this.hasFetchError) { return html` -
- - ${msg(`The interactive browser is not available.`)} - -
+ + ${msg(`The interactive browser is not available.`)} + `; } @@ -128,16 +180,12 @@ export class ProfileBrowser extends LiteElement { title=${msg("Interactive browser for creating browser profile")} src=${this.iframeSrc} @load=${this.onIframeLoad} - ${ref((el) => this.onIframeRef(el as HTMLIFrameElement))} >`; } if (this.browserId && !this.isIframeLoaded) { return html` -
+
`; @@ -146,37 +194,13 @@ export class ProfileBrowser extends LiteElement { return ""; } - private renderFullscreenButton() { - if (!this.browserId) return; - + private renderSidebarButton() { return html` -
- - this.isFullscreen - ? document.exitFullscreen() - : this.enterFullscreen("interactive-browser")} - > - ${this.isFullscreen - ? html` - - ${msg("Exit")} - ` - : html` - - ${msg("Fullscreen")} - `} - -
+ (this.showOriginSidebar = !this.showOriginSidebar)} + > `; } @@ -353,8 +377,8 @@ export class ProfileBrowser extends LiteElement { private async enterFullscreen(id: string) { try { document.getElementById(id)!.requestFullscreen({ - // Show browser navigation controls - navigationUI: "show", + // Hide browser navigation controls + navigationUI: "hide", }); } catch (err) { console.error(err); @@ -363,31 +387,17 @@ export class ProfileBrowser extends LiteElement { private onIframeLoad() { this.isIframeLoaded = true; - + try { + this.iframe?.contentWindow?.localStorage.setItem("uiTheme", '"default"'); + } catch (e) {} this.dispatchEvent(new CustomEvent("load", { detail: this.iframeSrc })); } - private onFullscreenChange = () => { + private onFullscreenChange = async () => { if (document.fullscreenElement) { this.isFullscreen = true; } else { this.isFullscreen = false; } }; - - private onIframeRef(el: HTMLIFrameElement) { - if (!el) return; - - el.addEventListener("load", () => { - // TODO see if we can make this work locally without CORs errors - try { - //el.style.width = "132%"; - el.contentWindow?.localStorage.setItem("uiTheme", '"default"'); - el.contentWindow?.localStorage.setItem( - "InspectorView.screencastSplitViewState", - `{"vertical":{"size":${ProfileBrowser.SIDE_BAR_WIDTH}}}` - ); - } catch (e) {} - }); - } } diff --git a/frontend/src/pages/org/browser-profiles-detail.ts b/frontend/src/pages/org/browser-profiles-detail.ts index ad2c9478..ba215b91 100644 --- a/frontend/src/pages/org/browser-profiles-detail.ts +++ b/frontend/src/pages/org/browser-profiles-detail.ts @@ -1,10 +1,10 @@ import { state, property } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; +import { when } from "lit/directives/when.js"; import { msg, localized, str } from "@lit/localize"; import type { AuthState } from "../../utils/AuthService"; import LiteElement, { html } from "../../utils/LiteElement"; -import { ProfileBrowser } from "../../components/profile-browser"; import { Profile } from "./types"; /** @@ -80,7 +80,7 @@ export class BrowserProfilesDetail extends LiteElement {
-

+

${this.profile?.name ? html`${this.profile?.name} -
-
-

${msg("Browser Profile")}

-
- -
-
-
- ${this.browserId - ? html` - ${msg( - "Interact with the browsing tool to make changes to your browser profile." - )} - ` - : ""} -
- -
- ${this.browserId && !this.isBrowserLoading - ? html` - ${msg("Cancel")} - ${msg("Save")} - ` - : html` - ${msg("Duplicate")} - `} -
-
- -
- (this.isBrowserLoaded = true)} - > - - ${this.browserId || this.isBrowserLoading - ? "" - : html` -
-

- ${msg( - "Load browser to view or edit websites in the profile." - )} -

- - ${msg("Load Browser")} -
- `} -
-
-
+
+
+
+

${msg("Browser Profile")}

+
+ ${when( + this.browserId || this.isBrowserLoading, + () => html` +
+ (this.isBrowserLoaded = true)} + > +
+ ${this.renderBrowserProfileControls()} +
+
+ `, + () => html`
+

+ ${msg( + "Edit the profile to make changes or view its present configuration" + )} +

+ ${msg( + "Edit Browser Profile" + )} +
` + )} +
+ ${when( + !(this.browserId || this.isBrowserLoading), + this.renderVisitedSites + )} +
`; } + private renderVisitedSites = () => { + return html` +
+
+

${msg("Visited Sites")}

+
+
+
    + ${this.profile?.origins.map((origin) => html`
  • ${origin}
  • `)} +
+
+
+ `; + }; + + private renderBrowserProfileControls() { + return html` +
+
+

+ ${msg( + "Interact with the browsing tool to set up the browser profile. Crawl configs that use this browser profile will behave as if they have logged into the same websites and have the same cookies that have been set here." + )} +

+
+
+ ${msg("Cancel")} + ${msg("Save Browser Profile")} +
+
+ `; + } + private renderMenu() { return html` diff --git a/frontend/src/pages/org/browser-profiles-new.ts b/frontend/src/pages/org/browser-profiles-new.ts index 414d0a34..48a7ad9a 100644 --- a/frontend/src/pages/org/browser-profiles-new.ts +++ b/frontend/src/pages/org/browser-profiles-new.ts @@ -88,27 +88,32 @@ export class BrowserProfilesNew extends LiteElement { ` : ""} -
-

- ${msg( - "Interact with the browsing tool to record your browser profile. You will complete and save your profile in the next step." - )} -

- - (this.isDialogVisible = true)} +
+
- ${msg("Next")} - -
+

+ ${msg( + "Interact with the browsing tool to record your browser profile. You will complete and save your profile in the next step." + )} +

- + (this.isDialogVisible = true)} + > + ${msg("Next")} + +
+ + +