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 (
+
+
+
+
+ {/* 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} />
+ }
+ />
}