diff --git a/package-lock.json b/package-lock.json index cb1d3f243..899a47dc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4167,29 +4167,6 @@ "resolved": "https://registry.npmjs.org/@stitches/core/-/core-1.2.8.tgz", "integrity": "sha512-Gfkvwk9o9kE9r9XNBmJRfV8zONvXThnm1tcuojL04Uy5uRyqg93DC83lDebl0rocZCfKSjUv+fWYtMQmEDJldg==" }, - "node_modules/@supabase/auth-ui-react": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@supabase/auth-ui-react/-/auth-ui-react-0.4.2.tgz", - "integrity": "sha512-NLP1udNtbteWDZYUoJKD/sDzi1BeZpS+CvUk1D0FwHevlVDT1fUf27sVLtrAgchSIQxHwZHTiUPJC9auCF3Zyw==", - "dependencies": { - "@stitches/core": "^1.2.8", - "@supabase/auth-ui-shared": "0.1.6", - "prop-types": "^15.7.2", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "peerDependencies": { - "@supabase/supabase-js": "^2.21.0" - } - }, - "node_modules/@supabase/auth-ui-shared": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@supabase/auth-ui-shared/-/auth-ui-shared-0.1.6.tgz", - "integrity": "sha512-dBlP2XR5KSSCBMgkWJMkc2UVA21V5AobKmekwIiHVvyVtzAiFqE5XWJiPV+kMlnRLzFXDeA0Z/CqdKTL/Kbs4A==", - "peerDependencies": { - "@supabase/supabase-js": "^2.21.0" - } - }, "node_modules/@supabase/functions-js": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.1.2.tgz", @@ -15714,8 +15691,8 @@ "@blocknote/core": "^0.9.2", "@emotion/react": "^11.4.0", "@hocuspocus/provider": "^2.4.0", - "@supabase/auth-ui-react": "^0.4.2", - "@supabase/auth-ui-shared": "^0.1.6", + "@supabase/auth-ui-react": "^0.4.5", + "@supabase/auth-ui-shared": "^0.1.7", "@supabase/supabase-js": "^2.26.0", "@syncedstore/yjs-reactive-bindings": "^0.5.1", "@tiptap/core": "^2.0.4", @@ -15770,6 +15747,29 @@ "vitest": "^0.33.0" } }, + "packages/editor/node_modules/@supabase/auth-ui-react": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/@supabase/auth-ui-react/-/auth-ui-react-0.4.5.tgz", + "integrity": "sha512-p7mZoD/iJKP7KorQ4F/RK4NfWDpXzop+LhMuHxkO5BahD+VpGIxwtykuXfZ0g7rijaKnA1BimdCBTCrV5EWTag==", + "dependencies": { + "@stitches/core": "^1.2.8", + "@supabase/auth-ui-shared": "0.1.7", + "prop-types": "^15.7.2", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "peerDependencies": { + "@supabase/supabase-js": "^2.21.0" + } + }, + "packages/editor/node_modules/@supabase/auth-ui-shared": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@supabase/auth-ui-shared/-/auth-ui-shared-0.1.7.tgz", + "integrity": "sha512-ueqyfCHVYX/ioehwL1ErH0+cZwiSzsIfZfhf326yJdDI0XExTKPV4lxPtWT1xx6c8A4FPPmT3kJKQaWs27pxCw==", + "peerDependencies": { + "@supabase/supabase-js": "^2.21.0" + } + }, "packages/editor/node_modules/@types/node": { "version": "16.18.41", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.41.tgz", diff --git a/packages/editor/package.json b/packages/editor/package.json index 2c79a2dce..9efced688 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -27,8 +27,8 @@ "@tiptap/core": "^2.0.4", "@blocknote/core": "^0.9.2", "@emotion/react": "^11.4.0", - "@supabase/auth-ui-react": "^0.4.2", - "@supabase/auth-ui-shared": "^0.1.6", + "@supabase/auth-ui-react": "^0.4.5", + "@supabase/auth-ui-shared": "^0.1.7", "@supabase/supabase-js": "^2.26.0", "@syncedstore/yjs-reactive-bindings": "^0.5.1", "@typecell-org/util": "^0.0.3", diff --git a/packages/editor/src/app/App.tsx b/packages/editor/src/app/App.tsx index 8522a993e..78ca79030 100644 --- a/packages/editor/src/app/App.tsx +++ b/packages/editor/src/app/App.tsx @@ -65,7 +65,6 @@ export const App = observer( sessionStore as SupabaseSessionStore, )} /> - Not implemented yet} /> { together.

- Create your own workspace and join the community on Discord to - share your thoughts, or contribute to the project on GitHub. + Create your own workspace and join the community on{" "} + + Discord + {" "} + to share your thoughts, or contribute to the project on{" "} + + GitHub + + .

Dive into the sneak-peeks below to check out some features we @@ -388,7 +401,7 @@ export const StartScreen = observer((props: { sessionStore: SessionStore }) => { target="_blank" href="https://discord.gg/TcJ9TRC3SV" rel="noreferrer"> - Chat on discord + Chat on Discord

  • diff --git a/packages/editor/src/app/supabase-auth/SupabaseSessionStore.ts b/packages/editor/src/app/supabase-auth/SupabaseSessionStore.ts index 44be39bc8..331b835fe 100644 --- a/packages/editor/src/app/supabase-auth/SupabaseSessionStore.ts +++ b/packages/editor/src/app/supabase-auth/SupabaseSessionStore.ts @@ -16,7 +16,6 @@ import ProfileResource from "../../store/ProfileResource"; import { TypeCellRemote } from "../../store/yjs-sync/remote/TypeCellRemote"; import { navigateRef } from "../GlobalNavigateRef"; - export type SupabaseClientType = ReturnType>; const colors = [ @@ -98,7 +97,7 @@ export class SupabaseSessionStore extends SessionStore { scheme: "typecell", authority: "typecell.org", path: "/" + uniqueId.generateId("document"), - }) + }), ); } @@ -110,11 +109,15 @@ export class SupabaseSessionStore extends SessionStore { isLoggedIn: computed, isLoaded: computed, }); - this.supabase = createClient(env.VITE_TYPECELL_SUPABASE_URL, env.VITE_TYPECELL_SUPABASE_ANON_KEY, { - auth: { - persistSession: persist, + this.supabase = createClient( + env.VITE_TYPECELL_SUPABASE_URL, + env.VITE_TYPECELL_SUPABASE_ANON_KEY, + { + auth: { + persistSession: persist, + }, }, - }); + ); this.initializeReactions(); } @@ -125,11 +128,10 @@ export class SupabaseSessionStore extends SessionStore { this.initialized = true; try { - const session = (await this.supabase.auth.getSession()).data.session || undefined; + const session = + (await this.supabase.auth.getSession()).data.session || undefined; let previousSessionId = session?.user.id; const cbData = this.supabase.auth.onAuthStateChange((event, session) => { - - // only trigger if user id changed if (session?.user.id !== previousSessionId) { previousSessionId = session?.user.id; @@ -137,6 +139,9 @@ export class SupabaseSessionStore extends SessionStore { console.error("error initializing sessionstore", e); }); } + if (event === "PASSWORD_RECOVERY") { + window.location.href = "/recover"; + } }); this._register({ dispose: cbData.data.subscription.unsubscribe, @@ -167,7 +172,7 @@ export class SupabaseSessionStore extends SessionStore { } const session = (await this.supabase.auth.getSession()).data.session; if (!session) { - throw new Error("unexpected: no session") + throw new Error("unexpected: no session"); } // create workspace @@ -184,7 +189,6 @@ export class SupabaseSessionStore extends SessionStore { remote.dispose(); } - // create profile const profileId = this.getIdentifierForNewDocument(); { @@ -195,7 +199,7 @@ export class SupabaseSessionStore extends SessionStore { const profile = ret.getSpecificType(ProfileResource); profile.workspaces.set("public", workspaceId.toString()); profile.username = username; - profile.joinedDate = Date.now() + profile.joinedDate = Date.now(); const avatar = session.user.user_metadata?.avatar_url; @@ -222,13 +226,15 @@ export class SupabaseSessionStore extends SessionStore { throw new Error(error.message); } - await this.updateStateFromAuthStore(session, true); } /** * Updates the state of sessionStore based on the internal matrixAuthStore.loggedIn */ - private async updateStateFromAuthStore(session: Session | undefined, isSignUp = false) { + private async updateStateFromAuthStore( + session: Session | undefined, + isSignUp = false, + ) { // TODO: make work in offline mode (save username offline) // TODO: don't trigger on refresh of other browser window @@ -245,7 +251,7 @@ export class SupabaseSessionStore extends SessionStore { ) { return; } - + let username = session.user.user_metadata.typecell_username; let profile_id = session.user.user_metadata.typecell_profile_nano_id; if (!username || !profile_id) { @@ -254,7 +260,7 @@ export class SupabaseSessionStore extends SessionStore { .select() .eq("owner_user_id", session?.user.id) .eq("is_username", true); - + if (usernameRes.data?.length === 1) { username = usernameRes.data[0].name; profile_id = usernameRes.data[0].document_nano_id; @@ -262,8 +268,8 @@ export class SupabaseSessionStore extends SessionStore { data: { typecell_username: username, typecell_profile_nano_id: profile_id, - } - }) + }, + }); } else { if (!navigateRef) { throw new Error("no global navigateRef"); @@ -272,7 +278,9 @@ export class SupabaseSessionStore extends SessionStore { this.userId = session.user.id; }); console.log("redirect"); - navigateRef.current?.("/username", { state: window.history?.state?.usr}); + navigateRef.current?.("/username", { + state: window.history?.state?.usr, + }); // runInAction(() => { // this.user = { // type: "user", @@ -297,7 +305,7 @@ export class SupabaseSessionStore extends SessionStore { userId: username, fullUserId: username, profileId: profile_id, - isSignUp + isSignUp, }; }); } diff --git a/packages/editor/src/app/supabase-auth/routes/Recover.tsx b/packages/editor/src/app/supabase-auth/routes/Recover.tsx new file mode 100644 index 000000000..a50a3285e --- /dev/null +++ b/packages/editor/src/app/supabase-auth/routes/Recover.tsx @@ -0,0 +1,71 @@ +import { observer } from "mobx-react-lite"; +import { Navigate, useLocation, useNavigate } from "react-router-dom"; + +import { Auth } from "@supabase/auth-ui-react"; +import { + // Import predefined theme + ThemeSupa, +} from "@supabase/auth-ui-shared"; +import { SessionStore } from "../../../store/local/SessionStore"; +import { Logo } from "../../main/components/Logo"; + +import { useEffect } from "react"; +import { SupabaseSessionStore } from "../SupabaseSessionStore"; +import AuthStyles from "./AuthStyles.module.css"; + +export const Recover = observer((props: { sessionStore: SessionStore }) => { + const { sessionStore } = props; + + const location = useLocation(); + const navigate = useNavigate(); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const from = (location.state as any)?.from?.pathname || "/"; + // let pageAfterLogin = window.location.origin + from; + + if (!sessionStore.isLoggedIn) { + return ; + } + + useEffect(() => { + const { data: authListener } = ( + sessionStore as SupabaseSessionStore + ).supabase.auth.onAuthStateChange((event) => { + if (event === "USER_UPDATED") { + // bit hacky, but otherwise supabase auth ui just displays a login screen and there's no way to excape. + // navigate to main page instead + navigate(from, { replace: true }); + } + }); + + return () => authListener.subscription.unsubscribe(); + }, [from, navigate, sessionStore]); + + const redirectTo = from; + + return ( +
    +
    +
    + +
    +
    +
    +
    + + {/*
    sdfsdf
    */} +
    +
    +
    + {/* Powered by Matrix */} +
    +
    + ); +}); diff --git a/packages/editor/src/app/supabase-auth/supabaseAuthProvider.tsx b/packages/editor/src/app/supabase-auth/supabaseAuthProvider.tsx index d567b7f9f..232831441 100644 --- a/packages/editor/src/app/supabase-auth/supabaseAuthProvider.tsx +++ b/packages/editor/src/app/supabase-auth/supabaseAuthProvider.tsx @@ -1,9 +1,10 @@ import { Route } from "react-router-dom"; +import { SupabaseSessionStore } from "./SupabaseSessionStore"; import { Login } from "./routes/Login"; +import { Recover } from "./routes/Recover"; import { Register } from "./routes/Register"; import { Username } from "./routes/Username"; -import { SupabaseSessionStore } from "./SupabaseSessionStore"; export const supabaseAuthProvider = { routes: { @@ -15,7 +16,10 @@ export const supabaseAuthProvider = { ), additionalRoutes: (sessionStore: SupabaseSessionStore) => ( <> - Not implemented yet} /> + } + /> }