diff --git a/frontend/src/features/browser-profiles/profile-browser-dialog.ts b/frontend/src/features/browser-profiles/profile-browser-dialog.ts index 036c2343f8..83b4dd7068 100644 --- a/frontend/src/features/browser-profiles/profile-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/profile-browser-dialog.ts @@ -13,6 +13,7 @@ import type { Dialog } from "@/components/ui/dialog"; import { bgClass, type BrowserConnectionChange, + type BrowserOriginsChange, type ProfileBrowser, } from "@/features/browser-profiles/profile-browser"; import type { @@ -24,6 +25,14 @@ import type { Profile } from "@/types/crawler"; import { isApiError } from "@/utils/api"; import { tw } from "@/utils/tailwind"; +enum BrowserStatus { + Initial, + Pending, + Ready, + Complete, + Error, +} + /** * @fires btrix-updated */ @@ -43,7 +52,7 @@ export class ProfileBrowserDialog extends BtrixElement { open = false; @state() - private isBrowserLoaded = false; + private browserStatus = BrowserStatus.Initial; @state() private showConfirmation = false; @@ -77,7 +86,7 @@ export class ProfileBrowserDialog extends BtrixElement { if (changedProperties.has("open")) { if (!this.open) { this.showConfirmation = false; - this.isBrowserLoaded = false; + this.browserStatus = BrowserStatus.Initial; this.#savedBrowserId = undefined; this.browserIdTask.abort(); } @@ -142,6 +151,7 @@ export class ProfileBrowserDialog extends BtrixElement { render() { const isCrawler = this.appState.isCrawler; const creatingNew = this.duplicating || !this.profile; + const incomplete = this.browserStatus !== BrowserStatus.Complete; const saving = this.saveProfileTask.status === TaskStatus.PENDING; return html` void this.dialog?.hide() : () => (this.showConfirmation = true)} > @@ -254,13 +266,13 @@ export class ProfileBrowserDialog extends BtrixElement { void this.submit()} > @@ -289,12 +301,16 @@ export class ProfileBrowserDialog extends BtrixElement { ? html` { - this.isBrowserLoaded = false; + this.browserStatus = BrowserStatus.Initial; }; private readonly onBrowserLoad = () => { - this.isBrowserLoaded = true; + this.browserStatus = BrowserStatus.Ready; }; private readonly onBrowserReload = () => { - this.isBrowserLoaded = false; + this.browserStatus = BrowserStatus.Pending; }; private readonly onBrowserError = () => { - this.isBrowserLoaded = false; + this.browserStatus = BrowserStatus.Error; + }; + + private readonly onBrowserOriginsChange = ( + e: CustomEvent, + ) => { + if (e.detail.origins.length) { + this.browserStatus = BrowserStatus.Complete; + } }; private readonly onBrowserConnectionChange = ( e: CustomEvent, ) => { - this.isBrowserLoaded = e.detail.connected; + this.browserStatus = e.detail.connected + ? BrowserStatus.Pending + : BrowserStatus.Initial; }; private async submit() { diff --git a/frontend/src/features/browser-profiles/profile-browser.ts b/frontend/src/features/browser-profiles/profile-browser.ts index 61023782e8..9a48753f9e 100644 --- a/frontend/src/features/browser-profiles/profile-browser.ts +++ b/frontend/src/features/browser-profiles/profile-browser.ts @@ -11,6 +11,7 @@ import { BtrixElement } from "@/classes/BtrixElement"; import { emptyMessage } from "@/layouts/emptyMessage"; import type { Profile } from "@/types/crawler"; import { isApiError, type APIError } from "@/utils/api"; +import { isNotEqual } from "@/utils/is-not-equal"; import { tw } from "@/utils/tailwind"; // Matches background of embedded browser @@ -31,6 +32,9 @@ export type BrowserNotAvailableError = { export type BrowserConnectionChange = { connected: boolean; }; +export type BrowserOriginsChange = { + origins: string[]; +}; const isPolling = (value: unknown): value is number => { return typeof value === "number"; @@ -52,6 +56,7 @@ const isPolling = (value: unknown): value is number => { * @fires btrix-browser-error * @fires btrix-browser-reload * @fires btrix-browser-connection-change + * @fires btrix-browser-origins-change Origins list has changed * @cssPart base * @cssPart browser * @cssPart iframe @@ -166,9 +171,24 @@ export class ProfileBrowser extends BtrixElement { if (!browser || isPolling(browser)) return; try { - const data = await this.pingBrowser(browser.id, signal); + const { origins } = await this.pingBrowser(browser.id, signal); + + if ( + this.originsTask.value && + origins && + isNotEqual(this.originsTask.value, origins) + ) { + this.dispatchEvent( + new CustomEvent( + "btrix-browser-origins-change", + { + detail: { origins }, + }, + ), + ); + } - return data.origins; + return origins || []; } catch (err) { if (isApiError(err) && err.details === "no_such_browser") { void this.onBrowserError(); diff --git a/frontend/src/features/browser-profiles/start-browser-dialog.ts b/frontend/src/features/browser-profiles/start-browser-dialog.ts index a9b9fa2a11..22ce2c18cd 100644 --- a/frontend/src/features/browser-profiles/start-browser-dialog.ts +++ b/frontend/src/features/browser-profiles/start-browser-dialog.ts @@ -300,9 +300,15 @@ export class StartBrowserDialog extends BtrixElement { }} > ${msg("New Site")} - - ${msg("Saved Sites")} - ${profile.origins.map(option)} + + ${when( + profile.origins.length, + () => html` + + ${msg("Saved Sites")} + ${profile.origins.map(option)} + `, + )} ${when(this.workflowOrigins.value, (seeds) => seeds.length ? html` diff --git a/frontend/src/pages/org/browser-profiles-list.ts b/frontend/src/pages/org/browser-profiles-list.ts index 4ace718c76..7917de49a2 100644 --- a/frontend/src/pages/org/browser-profiles-list.ts +++ b/frontend/src/pages/org/browser-profiles-list.ts @@ -521,6 +521,9 @@ export class BrowserProfilesList extends BtrixElement { (a, b) => (b && a && b > a ? b : a), data.created, ) || data.created; + const none = html` + + `; return html` - ${originsWithRemainder(data.origins)} + ${data.origins.length ? originsWithRemainder(data.origins) : none} ${this.localize.relativeDate(modifiedByAnyDate, { capitalize: true })} diff --git a/frontend/src/pages/org/browser-profiles/profile.ts b/frontend/src/pages/org/browser-profiles/profile.ts index 434e2e0c12..d28e373968 100644 --- a/frontend/src/pages/org/browser-profiles/profile.ts +++ b/frontend/src/pages/org/browser-profiles/profile.ts @@ -394,13 +394,21 @@ export class BrowserProfilesProfilePage extends BtrixElement { return when( this.profile, - (profile) => html` -
-
    - ${origins(profile)} -
-
- `, + (profile) => + profile.origins.length + ? html` +
+
    + ${origins(profile)} +
+
+ ` + : panelBody({ + content: emptyMessage({ + message: msg("No saved sites yet"), + detail: msg("Load a new URL to configure this profile."), + }), + }), originsSkeleton, ); }