diff --git a/web/next.config.js b/web/next.config.js
index 2877a646911..1a8d7a53a6b 100644
--- a/web/next.config.js
+++ b/web/next.config.js
@@ -13,7 +13,6 @@ const cspHeader = `
object-src 'none';
base-uri 'self';
form-action 'self';
- frame-ancestors 'none';
${
process.env.NEXT_PUBLIC_CLOUD_ENABLED === "true"
? "upgrade-insecure-requests;"
@@ -27,6 +26,17 @@ const nextConfig = {
publicRuntimeConfig: {
version,
},
+ images: {
+ // Used to fetch favicons
+ remotePatterns: [
+ {
+ protocol: "https",
+ hostname: "www.google.com",
+ port: "",
+ pathname: "/s2/favicons/**",
+ },
+ ],
+ },
async headers() {
return [
{
@@ -44,17 +54,12 @@ const nextConfig = {
key: "Referrer-Policy",
value: "strict-origin-when-cross-origin",
},
- {
- key: "X-Frame-Options",
- value: "DENY",
- },
{
key: "X-Content-Type-Options",
value: "nosniff",
},
{
key: "Permissions-Policy",
- // Deny all permissions by default
value:
"accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()",
},
diff --git a/web/package-lock.json b/web/package-lock.json
index d32345fe64f..0d1eb688f30 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -17,7 +17,9 @@
"@phosphor-icons/react": "^2.0.8",
"@radix-ui/react-checkbox": "^1.1.2",
"@radix-ui/react-dialog": "^1.1.2",
+ "@radix-ui/react-label": "^2.1.1",
"@radix-ui/react-popover": "^1.1.2",
+ "@radix-ui/react-radio-group": "^1.2.2",
"@radix-ui/react-select": "^2.1.2",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
@@ -77,6 +79,7 @@
"devDependencies": {
"@chromatic-com/playwright": "^0.10.0",
"@tailwindcss/typography": "^0.5.10",
+ "@types/chrome": "^0.0.287",
"chromatic": "^11.18.1",
"eslint": "^8.48.0",
"eslint-config-next": "^14.1.0",
@@ -2912,6 +2915,85 @@
}
}
},
+ "node_modules/@radix-ui/react-label": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.1.tgz",
+ "integrity": "sha512-UUw5E4e/2+4kFMH7+YxORXGWggtY6sM8WIwh5RZchhLuUg2H1hc98Py+pr8HMz6rdaYrK2t296ZEjYLOCO5uUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
+ "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",
+ "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-slot": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
+ "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-popover": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.2.tgz",
@@ -3063,6 +3145,196 @@
}
}
},
+ "node_modules/@radix-ui/react-radio-group": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.2.2.tgz",
+ "integrity": "sha512-E0MLLGfOP0l8P/NxgVzfXJ8w3Ch8cdO6UDzJfDChu4EJDy+/WdO5LqpdY8PYnCErkmZH3gZhDL1K7kQ41fAHuQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-presence": "1.1.2",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-roving-focus": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-use-previous": "1.1.0",
+ "@radix-ui/react-use-size": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
+ "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-collection": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.1.tgz",
+ "integrity": "sha512-LwT3pSho9Dljg+wY2KN2mrrh6y3qELfftINERIzBUO9e0N+t0oMTyn3k9iv+ZqgrwGkRnLpNJrsMv9BZlt2yuA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-slot": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
+ "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-context": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz",
+ "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-presence": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz",
+ "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-use-layout-effect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-primitive": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",
+ "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-roving-focus": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.1.tgz",
+ "integrity": "sha512-QE1RoxPGJ/Nm8Qmk0PxP8ojmoaS67i0s7hVssS7KuI2FQoc/uzVlZsqKfQvxPE6D8hICCPHJ4D88zNhT3OOmkw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-collection": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-controllable-state": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-slot": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
+ "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-roving-focus": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz",
@@ -4655,6 +4927,17 @@
"url": "https://github.com/sponsors/tannerlinsley"
}
},
+ "node_modules/@types/chrome": {
+ "version": "0.0.287",
+ "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.287.tgz",
+ "integrity": "sha512-wWhBNPNXZHwycHKNYnexUcpSbrihVZu++0rdp6GEk5ZgAglenLx+RwdEouh6FrHS0XQiOxSd62yaujM1OoQlZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/filesystem": "*",
+ "@types/har-format": "*"
+ }
+ },
"node_modules/@types/connect": {
"version": "3.4.36",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz",
@@ -4738,6 +5021,30 @@
"@types/estree": "*"
}
},
+ "node_modules/@types/filesystem": {
+ "version": "0.0.36",
+ "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.36.tgz",
+ "integrity": "sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/filewriter": "*"
+ }
+ },
+ "node_modules/@types/filewriter": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.33.tgz",
+ "integrity": "sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/har-format": {
+ "version": "1.2.16",
+ "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.16.tgz",
+ "integrity": "sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/hast": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
diff --git a/web/package.json b/web/package.json
index 4a52f11c9bc..3fdf30f8535 100644
--- a/web/package.json
+++ b/web/package.json
@@ -19,7 +19,9 @@
"@phosphor-icons/react": "^2.0.8",
"@radix-ui/react-checkbox": "^1.1.2",
"@radix-ui/react-dialog": "^1.1.2",
+ "@radix-ui/react-label": "^2.1.1",
"@radix-ui/react-popover": "^1.1.2",
+ "@radix-ui/react-radio-group": "^1.2.2",
"@radix-ui/react-select": "^2.1.2",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
@@ -79,6 +81,7 @@
"devDependencies": {
"@chromatic-com/playwright": "^0.10.0",
"@tailwindcss/typography": "^0.5.10",
+ "@types/chrome": "^0.0.287",
"chromatic": "^11.18.1",
"eslint": "^8.48.0",
"eslint-config-next": "^14.1.0",
diff --git a/web/src/app/admin/settings/AnonymousUserPath.tsx b/web/src/app/admin/settings/AnonymousUserPath.tsx
index 699b70f2583..b35a8d9aae6 100644
--- a/web/src/app/admin/settings/AnonymousUserPath.tsx
+++ b/web/src/app/admin/settings/AnonymousUserPath.tsx
@@ -5,7 +5,7 @@ import { useState } from "react";
import { PopupSpec } from "@/components/admin/connectors/Popup";
import { Button } from "@/components/ui/button";
-import { NEXT_PUBLIC_CLOUD_DOMAIN } from "@/lib/constants";
+import { NEXT_PUBLIC_WEB_DOMAIN } from "@/lib/constants";
import { ClipboardIcon } from "@/components/icons/icons";
import { Input } from "@/components/ui/input";
import { ThreeDotsLoader } from "@/components/Loading";
@@ -118,7 +118,7 @@ export function AnonymousUserPath({
- {NEXT_PUBLIC_CLOUD_DOMAIN}/anonymous/
+ {NEXT_PUBLIC_WEB_DOMAIN}/anonymous/
{
navigator.clipboard.writeText(
- `${NEXT_PUBLIC_CLOUD_DOMAIN}/anonymous/${anonymousUserPath}`
+ `${NEXT_PUBLIC_WEB_DOMAIN}/anonymous/${anonymousUserPath}`
);
setPopup({
message: "Invite link copied!",
diff --git a/web/src/app/auth/login/LoginPage.tsx b/web/src/app/auth/login/LoginPage.tsx
new file mode 100644
index 00000000000..cc10e5b74f0
--- /dev/null
+++ b/web/src/app/auth/login/LoginPage.tsx
@@ -0,0 +1,106 @@
+"use client";
+
+import { AuthTypeMetadata } from "@/lib/userSS";
+import { LoginText } from "./LoginText";
+import Link from "next/link";
+import { SignInButton } from "./SignInButton";
+import { EmailPasswordForm } from "./EmailPasswordForm";
+import { NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED } from "@/lib/constants";
+import Title from "@/components/ui/title";
+import { useSendAuthRequiredMessage } from "@/lib/extension/utils";
+
+export default function LoginPage({
+ authUrl,
+ authTypeMetadata,
+ nextUrl,
+ searchParams,
+ showPageRedirect,
+}: {
+ authUrl: string | null;
+ authTypeMetadata: AuthTypeMetadata | null;
+ nextUrl: string | null;
+ searchParams:
+ | {
+ [key: string]: string | string[] | undefined;
+ }
+ | undefined;
+ showPageRedirect?: boolean;
+}) {
+ useSendAuthRequiredMessage();
+ return (
+
+ {authUrl && authTypeMetadata && (
+ <>
+
+
+
+
+
+ >
+ )}
+
+ {authTypeMetadata?.authType === "cloud" && (
+
+
+
+
+
+
+ Create an account
+
+
+ {NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED && (
+
+ Reset Password
+
+ )}
+
+
+ )}
+
+ {authTypeMetadata?.authType === "basic" && (
+ <>
+
+
+
+
+
+
+
+ >
+ )}
+ {showPageRedirect && (
+
+ Don't have an account?{" "}
+ {
+ if (typeof window !== "undefined" && window.top) {
+ window.top.location.href = "/auth/signup";
+ } else {
+ window.location.href = "/auth/signup";
+ }
+ }}
+ className="text-link font-medium cursor-pointer"
+ >
+ Create an account
+
+
+ )}
+
+ );
+}
diff --git a/web/src/app/auth/login/SignInButton.tsx b/web/src/app/auth/login/SignInButton.tsx
index b06f9bad79b..b2d1a15be4f 100644
--- a/web/src/app/auth/login/SignInButton.tsx
+++ b/web/src/app/auth/login/SignInButton.tsx
@@ -46,7 +46,7 @@ export function SignInButton({
return (
{button}
diff --git a/web/src/app/auth/login/page.tsx b/web/src/app/auth/login/page.tsx
index 32ea1aa3734..1d30a82421a 100644
--- a/web/src/app/auth/login/page.tsx
+++ b/web/src/app/auth/login/page.tsx
@@ -7,18 +7,8 @@ import {
AuthTypeMetadata,
} from "@/lib/userSS";
import { redirect } from "next/navigation";
-import { SignInButton } from "./SignInButton";
-import { EmailPasswordForm } from "./EmailPasswordForm";
-import Title from "@/components/ui/title";
-import Text from "@/components/ui/text";
-import Link from "next/link";
-import { LoginText } from "./LoginText";
-import { getSecondsUntilExpiration } from "@/lib/time";
import AuthFlowContainer from "@/components/auth/AuthFlowContainer";
-import CardSection from "@/components/admin/CardSection";
-import { NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED } from "@/lib/constants";
-import { SettingsContext } from "@/components/settings/SettingsProvider";
-import { useContext } from "react";
+import LoginPage from "./LoginPage";
const Page = async (props: {
searchParams?: Promise<{ [key: string]: string | string[] | undefined }>;
@@ -49,13 +39,7 @@ const Page = async (props: {
}
// if user is already logged in, take them to the main app page
- const secondsTillExpiration = getSecondsUntilExpiration(currentUser);
- if (
- currentUser &&
- currentUser.is_active &&
- !currentUser.is_anonymous_user &&
- (secondsTillExpiration === null || secondsTillExpiration > 0)
- ) {
+ if (currentUser && currentUser.is_active && !currentUser.is_anonymous_user) {
if (authTypeMetadata?.requiresVerification && !currentUser.is_verified) {
return redirect("/auth/waiting-on-verification");
}
@@ -83,55 +67,12 @@ const Page = async (props: {
-
- {authUrl && authTypeMetadata && (
- <>
-
-
-
-
-
- >
- )}
-
- {authTypeMetadata?.authType === "cloud" && (
-
-
-
-
-
-
- {NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED && (
-
- Reset Password
-
- )}
-
-
- )}
-
- {authTypeMetadata?.authType === "basic" && (
- <>
-
-
-
-
-
-
-
- >
- )}
-
+
);
diff --git a/web/src/app/chat/ChatIntro.tsx b/web/src/app/chat/ChatIntro.tsx
index d86eb2315e9..1d9ef435377 100644
--- a/web/src/app/chat/ChatIntro.tsx
+++ b/web/src/app/chat/ChatIntro.tsx
@@ -14,7 +14,7 @@ export function ChatIntro({ selectedPersona }: { selectedPersona: Persona }) {
setHoveredAssistant(true)}
onMouseLeave={() => setHoveredAssistant(false)}
- className="p-4 scale-[.7] cursor-pointer border-dashed rounded-full flex border border-gray-300 border-2 border-dashed"
+ className="mobile:hidden p-4 scale-[.7] cursor-pointer border-dashed rounded-full flex border border-gray-300 border-2 border-dashed"
>
-
+
{hoveredAssistant && (
)}
diff --git a/web/src/app/chat/ChatPage.tsx b/web/src/app/chat/ChatPage.tsx
index 0548bc3c558..af944f0b9a1 100644
--- a/web/src/app/chat/ChatPage.tsx
+++ b/web/src/app/chat/ChatPage.tsx
@@ -1,6 +1,6 @@
"use client";
-import { useRouter, useSearchParams } from "next/navigation";
+import { redirect, useRouter, useSearchParams } from "next/navigation";
import {
BackendChatSession,
BackendMessage,
@@ -52,13 +52,11 @@ import {
useLayoutEffect,
useRef,
useState,
- useMemo,
} from "react";
import { usePopup } from "@/components/admin/connectors/Popup";
import { SEARCH_PARAM_NAMES, shouldSubmitOnLoad } from "./searchParams";
import { useDocumentSelection } from "./useDocumentSelection";
import { LlmOverride, useFilters, useLlmOverride } from "@/lib/hooks";
-import { computeAvailableFilters } from "@/lib/filters";
import { ChatState, FeedbackType, RegenerationState } from "./types";
import { ChatFilters } from "./documentSidebar/ChatFilters";
import { OnyxInitializingLoader } from "@/components/OnyxInitializingLoader";
@@ -110,7 +108,11 @@ import AssistantBanner from "../../components/assistants/AssistantBanner";
import TextView from "@/components/chat_search/TextView";
import AssistantSelector from "@/components/chat_search/AssistantSelector";
import { Modal } from "@/components/Modal";
-import { createPostponedAbortSignal } from "next/dist/server/app-render/dynamic-rendering";
+import { useSendMessageToParent } from "@/lib/extension/utils";
+import {
+ CHROME_MESSAGE,
+ SUBMIT_MESSAGE_TYPES,
+} from "@/lib/extension/constants";
const TEMP_USER_MESSAGE_ID = -1;
const TEMP_ASSISTANT_MESSAGE_ID = -2;
@@ -120,10 +122,12 @@ export function ChatPage({
toggle,
documentSidebarInitialWidth,
toggledSidebar,
+ firstMessage,
}: {
toggle: (toggled?: boolean) => void;
documentSidebarInitialWidth?: number;
toggledSidebar: boolean;
+ firstMessage?: string;
}) {
const router = useRouter();
const searchParams = useSearchParams();
@@ -140,6 +144,7 @@ export function ChatPage({
shouldShowWelcomeModal,
refreshChatSessions,
} = useChatContext();
+
function useScreenSize() {
const [screenSize, setScreenSize] = useState({
width: typeof window !== "undefined" ? window.innerWidth : 0,
@@ -192,9 +197,6 @@ export function ChatPage({
const { user, isAdmin } = useUser();
const slackChatId = searchParams.get("slackChatId");
const existingChatIdRaw = searchParams.get("chatId");
- const [sendOnLoad, setSendOnLoad] = useState
(
- searchParams.get(SEARCH_PARAM_NAMES.SEND_ON_LOAD)
- );
const modelVersionFromSearchParams = searchParams.get(
SEARCH_PARAM_NAMES.STRUCTURED_MODEL
@@ -210,24 +212,34 @@ export function ChatPage({
toggle(false);
}
}, [user]);
- // Effect to handle sendOnLoad
- useEffect(() => {
- if (sendOnLoad) {
- const newSearchParams = new URLSearchParams(searchParams.toString());
- newSearchParams.delete(SEARCH_PARAM_NAMES.SEND_ON_LOAD);
- // Update the URL without the send-on-load parameter
- router.replace(`?${newSearchParams.toString()}`, { scroll: false });
+ const processSearchParamsAndSubmitMessage = (searchParamsString: string) => {
+ const newSearchParams = new URLSearchParams(searchParamsString);
+ const message = newSearchParams.get("user-prompt");
- // Update our local state to reflect the change
- setSendOnLoad(null);
+ filterManager.buildFiltersFromQueryString(
+ newSearchParams.toString(),
+ availableSources,
+ documentSets.map((ds) => ds.name),
+ tags
+ );
- // If there's a message, submit it
- if (message) {
- onSubmit({ messageOverride: message });
- }
+ const fileDescriptorString = newSearchParams.get(SEARCH_PARAM_NAMES.FILES);
+ const overrideFileDescriptors: FileDescriptor[] = fileDescriptorString
+ ? JSON.parse(decodeURIComponent(fileDescriptorString))
+ : [];
+
+ newSearchParams.delete(SEARCH_PARAM_NAMES.SEND_ON_LOAD);
+
+ router.replace(`?${newSearchParams.toString()}`, { scroll: false });
+
+ // If there's a message, submit it
+ if (message) {
+ console.log("SUBMITTING MESSAGE");
+ setSubmittedMessage(message);
+ onSubmit({ messageOverride: message, overrideFileDescriptors });
}
- }, [sendOnLoad, searchParams, router]);
+ };
const existingChatSessionId = existingChatIdRaw ? existingChatIdRaw : null;
@@ -312,14 +324,6 @@ export function ChatPage({
const noAssistants = liveAssistant == null || liveAssistant == undefined;
const availableSources = ccPairs.map((ccPair) => ccPair.source);
- const [finalAvailableSources, finalAvailableDocumentSets] =
- computeAvailableFilters({
- selectedPersona: availableAssistants.find(
- (assistant) => assistant.id === liveAssistant?.id
- ),
- availableSources: availableSources,
- availableDocumentSets: documentSets,
- });
// always set the model override for the chat session, when an assistant, llm provider, or user preference exists
useEffect(() => {
@@ -399,8 +403,6 @@ export function ChatPage({
setIsReady(true);
}, []);
- // this is triggered every time the user switches which chat
- // session they are using
useEffect(() => {
const priorChatSessionId = chatSessionIdRef.current;
const loadedSessionId = loadedIdSessionRef.current;
@@ -456,7 +458,6 @@ export function ChatPage({
}
return;
}
- setIsReady(true);
const shouldScrollToBottom =
visibleRange.get(existingChatSessionId) === undefined ||
visibleRange.get(existingChatSessionId)?.end == 0;
@@ -651,10 +652,10 @@ export function ChatPage({
currentMessageMap(completeMessageDetail)
);
- const [submittedMessage, setSubmittedMessage] = useState("");
+ const [submittedMessage, setSubmittedMessage] = useState(firstMessage || "");
const [chatState, setChatState] = useState