Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 25 additions & 25 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 0 additions & 1 deletion packages/editor/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ export const App = observer(
sessionStore as SupabaseSessionStore,
)}
/>
<Route path="/recover" element={<div>Not implemented yet</div>} />
<Route
path="/login"
element={props.authProvider.routes.login(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,21 @@ export const StartScreen = observer((props: { sessionStore: SessionStore }) => {
together.
</p>
<p>
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{" "}
<a
target="_blank"
href="https://discord.gg/TcJ9TRC3SV"
rel="noreferrer">
Discord
</a>{" "}
to share your thoughts, or contribute to the project on{" "}
<a
target="_blank"
href="https://github.com/TypeCellOS/TypeCell"
rel="noreferrer">
GitHub
</a>
.
</p>
<p>
Dive into the sneak-peeks below to check out some features we
Expand Down Expand Up @@ -388,7 +401,7 @@ export const StartScreen = observer((props: { sessionStore: SessionStore }) => {
target="_blank"
href="https://discord.gg/TcJ9TRC3SV"
rel="noreferrer">
<span>Chat on discord</span>
<span>Chat on Discord</span>
</a>
</li>
<li>
Expand Down
48 changes: 28 additions & 20 deletions packages/editor/src/app/supabase-auth/SupabaseSessionStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<typeof createClient<Database>>;

const colors = [
Expand Down Expand Up @@ -98,7 +97,7 @@ export class SupabaseSessionStore extends SessionStore {
scheme: "typecell",
authority: "typecell.org",
path: "/" + uniqueId.generateId("document"),
})
}),
);
}

Expand All @@ -110,11 +109,15 @@ export class SupabaseSessionStore extends SessionStore {
isLoggedIn: computed,
isLoaded: computed,
});
this.supabase = createClient<Database>(env.VITE_TYPECELL_SUPABASE_URL, env.VITE_TYPECELL_SUPABASE_ANON_KEY, {
auth: {
persistSession: persist,
this.supabase = createClient<Database>(
env.VITE_TYPECELL_SUPABASE_URL,
env.VITE_TYPECELL_SUPABASE_ANON_KEY,
{
auth: {
persistSession: persist,
},
},
});
);
this.initializeReactions();
}

Expand All @@ -125,18 +128,20 @@ 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;
this.updateStateFromAuthStore(session || undefined).catch((e) => {
console.error("error initializing sessionstore", e);
});
}
if (event === "PASSWORD_RECOVERY") {
window.location.href = "/recover";
}
});
this._register({
dispose: cbData.data.subscription.unsubscribe,
Expand Down Expand Up @@ -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
Expand All @@ -184,7 +189,6 @@ export class SupabaseSessionStore extends SessionStore {
remote.dispose();
}


// create profile
const profileId = this.getIdentifierForNewDocument();
{
Expand All @@ -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;

Expand All @@ -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

Expand All @@ -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) {
Expand All @@ -254,16 +260,16 @@ 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;
await this.supabase.auth.updateUser({
data: {
typecell_username: username,
typecell_profile_nano_id: profile_id,
}
})
},
});
} else {
if (!navigateRef) {
throw new Error("no global navigateRef");
Expand All @@ -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",
Expand All @@ -297,7 +305,7 @@ export class SupabaseSessionStore extends SessionStore {
userId: username,
fullUserId: username,
profileId: profile_id,
isSignUp
isSignUp,
};
});
}
Expand Down
71 changes: 71 additions & 0 deletions packages/editor/src/app/supabase-auth/routes/Recover.tsx
Original file line number Diff line number Diff line change
@@ -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 <Navigate to={from} replace={true} />;
}

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 (
<div className={AuthStyles.AuthPage}>
<div className={AuthStyles.AuthHeader}>
<div className={AuthStyles.AuthHeaderLogo}>
<Logo></Logo>
</div>
</div>
<div className={AuthStyles.AuthBody}>
<div className={AuthStyles.AuthForm}>
<Auth
magicLink={true}
supabaseClient={(sessionStore as SupabaseSessionStore).supabase}
view="update_password"
appearance={{ theme: ThemeSupa }}
redirectTo={redirectTo}
providers={["google", "github"]}
/>
{/* <div className={AuthStyles.AuthFormFooter}>sdfsdf</div> */}
</div>
</div>
<div className={AuthStyles.AuthFooter}>
{/* <HelperMessage>Powered by Matrix</HelperMessage> */}
</div>
</div>
);
});
Original file line number Diff line number Diff line change
@@ -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: {
Expand All @@ -15,7 +16,10 @@ export const supabaseAuthProvider = {
),
additionalRoutes: (sessionStore: SupabaseSessionStore) => (
<>
<Route path="/recover" element={<div>Not implemented yet</div>} />
<Route
path="/recover"
element={<Recover sessionStore={sessionStore} />}
/>
<Route
path="/username"
element={<Username sessionStore={sessionStore} />}
Expand Down