diff --git a/README.md b/README.md
index 727196d5..c0938587 100644
--- a/README.md
+++ b/README.md
@@ -89,12 +89,12 @@ You can now deploy the directory `packages/client/dist`.
The app currently needs the following routes:
-- `/server`
-- `/channel`
-- `/dev`
-- `/friends`
-- `/app`
+- `/login`
- `/pwa`
+- `/dev`
- `/settings`
+- `/friends`
+- `/server`
+- `/channel`
-This corresponds to [Content.tsx#L33](packages/client/src/interface/Content.tsx).
+This corresponds to [Content.tsx#L33](packages/client/src/index.tsx).
diff --git a/packages/client/assets b/packages/client/assets
index e96fb7eb..086faa65 160000
--- a/packages/client/assets
+++ b/packages/client/assets
@@ -1 +1 @@
-Subproject commit e96fb7eb10b9fe79fc9674233c2bdda1d30c9f1f
+Subproject commit 086faa6516ee01b25463231779b417d26a97f04f
diff --git a/packages/client/components/auth/src/flows/Flow.tsx b/packages/client/components/auth/src/flows/Flow.tsx
index d69fb4b2..5e0c1d53 100644
--- a/packages/client/components/auth/src/flows/Flow.tsx
+++ b/packages/client/components/auth/src/flows/Flow.tsx
@@ -10,8 +10,12 @@ import wave from "./wave.svg";
* Container for authentication page flows
*/
export const FlowBase = styled(Column)`
- background: ${(props) =>
- props.theme!.colours["messaging-message-box-background"]};
+ background: ${
+ (props) =>
+ props.theme!.colours[
+ "messaging-message-box-background"
+ ] /* TODO: change and in other places */
+ };
color: ${(props) => props.theme!.colours["messaging-message-box-foreground"]};
/* background-color: rgba(36, 36, 36, 0.75);
diff --git a/packages/client/components/auth/src/flows/FlowConfirmReset.tsx b/packages/client/components/auth/src/flows/FlowConfirmReset.tsx
index 5f635583..ac1994c4 100644
--- a/packages/client/components/auth/src/flows/FlowConfirmReset.tsx
+++ b/packages/client/components/auth/src/flows/FlowConfirmReset.tsx
@@ -28,7 +28,7 @@ export default function FlowConfirmReset() {
remove_sessions,
});
- navigate("../..", { replace: true });
+ navigate("/login/auth", { replace: true });
}
return (
@@ -39,7 +39,7 @@ export default function FlowConfirmReset() {
- {t("login.remembered")}
+ {t("login.remembered")}
>
);
diff --git a/packages/client/components/auth/src/flows/FlowCreate.tsx b/packages/client/components/auth/src/flows/FlowCreate.tsx
index f5ed166d..6084c364 100644
--- a/packages/client/components/auth/src/flows/FlowCreate.tsx
+++ b/packages/client/components/auth/src/flows/FlowCreate.tsx
@@ -7,6 +7,7 @@ import MdArrowBack from "@material-design-icons/svg/filled/arrow_back.svg?compon
import { clientController } from "../../../client";
+import { FlowTitle } from "./Flow";
import { setFlowCheckEmail } from "./FlowCheck";
import { Fields, Form } from "./Form";
@@ -43,9 +44,9 @@ export default function FlowCreate() {
return (
<>
- {/*
+
{t("login.welcome2")}
- */}
+
- {t("login.remembered")}
+ {t("login.remembered")}
>
);
diff --git a/packages/client/components/auth/src/flows/FlowReset.tsx b/packages/client/components/auth/src/flows/FlowReset.tsx
index 37fb86dc..8ddbc0b1 100644
--- a/packages/client/components/auth/src/flows/FlowReset.tsx
+++ b/packages/client/components/auth/src/flows/FlowReset.tsx
@@ -40,7 +40,7 @@ export default function FlowReset() {
- {t("login.remembered")}
+ {t("login.remembered")}
{import.meta.env.DEV && (
- {t("login.remembered")}
+ {t("login.remembered")}
@@ -95,7 +95,7 @@ export default function FlowVerify() {
- {t("login.remembered")}
+ {t("login.remembered")}
diff --git a/packages/client/components/auth/src/flows/Form.tsx b/packages/client/components/auth/src/flows/Form.tsx
index b1ee9f51..b1e56588 100644
--- a/packages/client/components/auth/src/flows/Form.tsx
+++ b/packages/client/components/auth/src/flows/Form.tsx
@@ -1,6 +1,8 @@
import HCaptcha, { HCaptchaFunctions } from "solid-hcaptcha";
import { For, JSX, Show, createSignal } from "solid-js";
+import { cva } from "styled-system/css";
+
import { mapAnyError } from "@revolt/client";
import { useTranslation } from "@revolt/i18n";
import { Checkbox, Column, FormGroup, Input, Typography } from "@revolt/ui";
@@ -8,7 +10,7 @@ import { Checkbox, Column, FormGroup, Input, Typography } from "@revolt/ui";
/**
* Available field types
*/
-type Field = "email" | "password" | "new-password" | "log-out";
+type Field = "email" | "password" | "new-password" | "log-out" | "username";
/**
* Properties to apply to fields
@@ -38,9 +40,24 @@ const useFieldConfiguration = () => {
"log-out": {
name: () => t("login.log_out_other"),
},
+ username: {
+ minLength: 2,
+ type: "text",
+ autocomplete: "none",
+ name: () => t("login.username"),
+ placeholder: () => t("login.enter.username"),
+ },
};
};
+const labelRow = cva({
+ base: {
+ gap: "var(--gap-sm)",
+ display: "flex",
+ alignItems: "center",
+ },
+});
+
interface FieldProps {
/**
* Fields to gather
@@ -67,11 +84,12 @@ export function Fields(props: FieldProps) {
{(field) => (
{field === "log-out" ? (
-
+
) : (
<>
diff --git a/packages/client/components/client/Controller.ts b/packages/client/components/client/Controller.ts
index f1a68278..fd7411aa 100644
--- a/packages/client/components/client/Controller.ts
+++ b/packages/client/components/client/Controller.ts
@@ -138,9 +138,9 @@ class Lifecycle {
this.client.on("ready", this.onReady);
}
- #enter(state: State) {
- console.debug("Entering state", state);
- this.#setStateSetter(state);
+ #enter(nextState: State) {
+ console.debug("Entering state", nextState);
+ this.#setStateSetter(nextState);
// Clean up retry timer
if (this.#retryTimeout) {
@@ -148,26 +148,42 @@ class Lifecycle {
this.#retryTimeout = undefined;
}
- switch (state) {
+ switch (nextState) {
case State.LoggingIn:
+ this.client.api.get("/onboard/hello").then(({ onboarding }) => {
+ if (onboarding) {
+ this.transition({
+ type: TransitionType.NoUser,
+ });
+ } else {
+ this.client.connect();
+ }
+ });
+
+ break;
case State.Connecting:
case State.Reconnecting:
this.client.connect();
break;
case State.Connected:
+ state.auth.markValid();
this.#setLoadedOnce(true);
this.#connectionFailures = 0;
break;
case State.Dispose:
this.dispose();
- this.#enter(State.Ready);
+ this.transition({
+ type: TransitionType.Ready,
+ });
this.#setLoadedOnce(false);
break;
case State.Disconnected:
this.#connectionFailures++;
if (!navigator.onLine) {
- this.#enter(State.Offline);
+ this.transition({
+ type: TransitionType.DeviceOffline,
+ });
} else {
const retryIn =
(Math.pow(2, this.#connectionFailures) - 1) *
@@ -181,7 +197,9 @@ class Lifecycle {
this.#retryTimeout = setTimeout(() => {
this.#retryTimeout = undefined;
- this.#enter(State.Reconnecting);
+ this.transition({
+ type: TransitionType.Retry,
+ });
}, retryIn * 1e3) as never;
}
break;
@@ -460,6 +478,7 @@ export default class ClientController {
_id: session._id,
token: session.token,
userId: session.user_id,
+ valid: false,
};
state.auth.setSession(createdSession);
@@ -469,6 +488,16 @@ export default class ClientController {
});
}
+ async selectUsername(username: string) {
+ await this.lifecycle.client.api.post("/onboard/complete", {
+ username,
+ });
+
+ this.lifecycle.transition({
+ type: TransitionType.UserCreated,
+ });
+ }
+
logout() {
state.auth.removeSession();
this.lifecycle.transition({
diff --git a/packages/client/components/i18n/locales b/packages/client/components/i18n/locales
index 1f0a96a7..62908308 160000
--- a/packages/client/components/i18n/locales
+++ b/packages/client/components/i18n/locales
@@ -1 +1 @@
-Subproject commit 1f0a96a7c93a187fed5f2a8cce218c406a62b7d2
+Subproject commit 6290830831cac101224faa4a6d29d4ba26c8a1cd
diff --git a/packages/client/components/state/stores/Auth.ts b/packages/client/components/state/stores/Auth.ts
index 2a899c99..2933d5a0 100644
--- a/packages/client/components/state/stores/Auth.ts
+++ b/packages/client/components/state/stores/Auth.ts
@@ -9,6 +9,7 @@ export type Session = {
_id: string;
token: string;
userId: string;
+ valid: boolean;
};
export type TypeAuth = {
@@ -39,6 +40,7 @@ export class Auth extends AbstractStore<"auth", TypeAuth> {
_id: CONFIGURATION.DEVELOPMENT_SESSION_ID ?? "0",
token: CONFIGURATION.DEVELOPMENT_TOKEN,
userId: CONFIGURATION.DEVELOPMENT_USER_ID,
+ valid: true,
});
}
@@ -70,12 +72,14 @@ export class Auth extends AbstractStore<"auth", TypeAuth> {
if (
typeof input.session._id === "string" &&
typeof input.session.token === "string" &&
- typeof input.session.userId === "string"
+ typeof input.session.userId === "string" &&
+ input.session.valid
) {
session = {
_id: input.session._id,
token: input.session.token,
userId: input.session.userId,
+ valid: true,
};
}
}
@@ -107,4 +111,14 @@ export class Auth extends AbstractStore<"auth", TypeAuth> {
removeSession() {
this.set("session", undefined!);
}
+
+ /**
+ * Mark current session as valid
+ */
+ markValid() {
+ const session = this.get().session;
+ if (session && !session.valid) {
+ this.set("session", "valid", true);
+ }
+ }
}
diff --git a/packages/client/src/interface/Home.tsx b/packages/client/src/interface/Home.tsx
index ecdd81eb..723c6937 100644
--- a/packages/client/src/interface/Home.tsx
+++ b/packages/client/src/interface/Home.tsx
@@ -24,10 +24,15 @@ import {
styled,
} from "@revolt/ui";
-import wideSvg from "../../../client/public/assets/wide.svg";
+import RevoltSvg from "../../public/assets/wordmark_wide_500px.svg?component-solid";
import { HeaderIcon } from "./common/CommonHeader";
+const Logo = styled(RevoltSvg)`
+ width: 240px;
+ fill: ${(props) => props.theme!.colours["foreground"]};
+`;
+
/**
* Base layout of the home page (i.e. the header/background)
*/
@@ -112,11 +117,12 @@ export function HomePage() {
Home
-
- {t("app.special.modals.onboarding.welcome")}
-
-
-
+
+
+ {t("app.special.modals.onboarding.welcome")}
+
+
+