-
-
-
-
-
Login/Signup is disabled or the server is down/under maintenance.
-
-
-
-
-
- login
-
-
-
-
-
-
-
-
-
diff --git a/frontend/src/index.html b/frontend/src/index.html
index c4ea32a36413..26f1c442e032 100644
--- a/frontend/src/index.html
+++ b/frontend/src/index.html
@@ -37,7 +37,9 @@
diff --git a/frontend/src/styles/index.scss b/frontend/src/styles/index.scss
index b74444aebaae..7e047a112b5c 100644
--- a/frontend/src/styles/index.scss
+++ b/frontend/src/styles/index.scss
@@ -17,9 +17,9 @@
@layer custom-styles {
@import "buttons", "404", "ads", "account", "animations", "caret",
- "commandline", "core", "fonts", "inputs", "keymap", "login", "monkey",
- "popups", "scroll", "settings", "account-settings", "test", "loading",
- "friends", "media-queries";
+ "commandline", "core", "fonts", "inputs", "keymap", "monkey", "popups",
+ "scroll", "settings", "account-settings", "test", "loading", "friends",
+ "media-queries";
.chartCanvas {
width: 100% !important;
diff --git a/frontend/src/styles/login.scss b/frontend/src/styles/login.scss
deleted file mode 100644
index 6395672c210f..000000000000
--- a/frontend/src/styles/login.scss
+++ /dev/null
@@ -1,79 +0,0 @@
-.pageLogin {
- display: flex;
- grid-auto-flow: column;
- gap: 1rem;
- justify-content: space-around;
- align-items: center;
- height: 100%;
-
- .side {
- display: grid;
- gap: 0.5rem;
- justify-content: center;
- grid-template-columns: 1fr;
-
- input[type="email"],
- input[type="password"],
- input[type="text"] {
- width: 17rem;
- }
-
- .title {
- display: inline-flex;
- align-items: baseline;
- color: var(--sub-color);
- i {
- margin-right: 0.5em;
- }
- }
-
- &.login {
- #forgotPasswordButton {
- // height: 0;
- font-size: 0.75rem;
- // margin-left: -0.5em;
- justify-content: right;
- }
-
- .providers {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 1rem;
- }
-
- .orWithLine {
- // height: 2.25rem;
- display: grid;
- grid-template-columns: 1fr auto 1fr;
- align-items: center;
- gap: 1rem;
- .line {
- background: var(--sub-alt-color);
- width: 100%;
- height: 0.25em;
- border-radius: var(--roundness);
- }
- }
- .checkbox {
- height: 1.5rem;
- align-items: center;
- }
- }
- }
-
- form {
- display: grid;
- gap: 0.5rem;
- width: 100%;
- }
-
- .preloader {
- position: fixed;
- left: 50%;
- top: 50%;
- font-size: 2rem;
- transform: translate(-50%, -50%);
- color: var(--main-color);
- transition: 0.25s;
- }
-}
diff --git a/frontend/src/styles/tailwind.css b/frontend/src/styles/tailwind.css
index 42a8040255cd..68ae21a5ea8d 100644
--- a/frontend/src/styles/tailwind.css
+++ b/frontend/src/styles/tailwind.css
@@ -91,3 +91,14 @@
padding: 0;
}
}
+
+@layer utilities {
+ .autofill-fix:-webkit-autofill,
+ .autofill-fix:-webkit-autofill:hover,
+ .autofill-fix:-webkit-autofill:focus {
+ @apply border-none font-(--font) caret-(--text-color) font-[inherit];
+ outline: 0.15em solid var(--main-color);
+ -webkit-text-fill-color: var(--text-color);
+ -webkit-box-shadow: 0 0 0 1000000px var(--sub-alt-color) inset;
+ }
+}
diff --git a/frontend/src/ts/ape/adapters/ts-rest-adapter.ts b/frontend/src/ts/ape/adapters/ts-rest-adapter.ts
index 54d6d5ed3bc9..6df7a3b150d3 100644
--- a/frontend/src/ts/ape/adapters/ts-rest-adapter.ts
+++ b/frontend/src/ts/ape/adapters/ts-rest-adapter.ts
@@ -10,7 +10,7 @@ import {
COMPATIBILITY_CHECK,
COMPATIBILITY_CHECK_HEADER,
} from "@monkeytype/contracts";
-import { addBanner } from "../../stores/banners";
+import { addBanner } from "../../states/banners";
let bannerShownThisSession = false;
diff --git a/frontend/src/ts/ape/config.ts b/frontend/src/ts/ape/config.ts
index d2fff58421de..7bc1402587db 100644
--- a/frontend/src/ts/ape/config.ts
+++ b/frontend/src/ts/ape/config.ts
@@ -1,6 +1,6 @@
import { Config } from "@monkeytype/schemas/configs";
import { isAuthenticated } from "../firebase";
-import { showErrorNotification } from "../stores/notifications";
+import { showErrorNotification } from "../states/notifications";
import Ape from ".";
export async function saveConfig(config: Partial
): Promise {
diff --git a/frontend/src/ts/auth.tsx b/frontend/src/ts/auth.tsx
index e0dcd87ee26f..5b25cd7c4fb8 100644
--- a/frontend/src/ts/auth.tsx
+++ b/frontend/src/ts/auth.tsx
@@ -25,15 +25,24 @@ import {
import { showPopup } from "./modals/simple-modals-base";
import * as AuthEvent from "./observables/auth-event";
import * as Sentry from "./sentry";
-import { showLoaderBar, hideLoaderBar } from "./signals/loader-bar";
-import { addBanner } from "./stores/banners";
+import { addBanner } from "./states/banners";
+import { showLoaderBar, hideLoaderBar } from "./states/loader-bar";
import {
showNoticeNotification,
showErrorNotification,
showSuccessNotification,
-} from "./stores/notifications";
+} from "./states/notifications";
import { createErrorMessage } from "./utils/error";
+export type AuthResult =
+ | {
+ success: true;
+ }
+ | {
+ success: false;
+ message: string;
+ };
+
export const gmailProvider = new GoogleAuthProvider();
export const githubProvider = new GithubAuthProvider();
@@ -156,15 +165,7 @@ export async function signIn(
email: string,
password: string,
rememberMe: boolean,
-): Promise<
- | {
- success: true;
- }
- | {
- success: false;
- message: string;
- }
-> {
+): Promise {
if (!isAuthAvailable()) {
return { success: false, message: "Authentication uninitialized" };
}
@@ -182,15 +183,7 @@ export async function signIn(
async function signInWithProvider(
provider: AuthProvider,
rememberMe: boolean,
-): Promise<
- | {
- success: true;
- }
- | {
- success: false;
- message: string;
- }
-> {
+): Promise {
if (!isAuthAvailable()) {
return { success: false, message: "Authentication uninitialized" };
}
@@ -198,35 +191,20 @@ async function signInWithProvider(
const { error } = await tryCatch(signInWithPopup(provider, rememberMe));
if (error !== null) {
- if (error.message !== "") {
- showErrorNotification(error.message);
- }
return { success: false, message: error.message };
}
return { success: true };
}
-export async function signInWithGoogle(rememberMe: boolean): Promise<
- | {
- success: true;
- }
- | {
- success: false;
- message: string;
- }
-> {
+export async function signInWithGoogle(
+ rememberMe: boolean,
+): Promise {
return signInWithProvider(gmailProvider, rememberMe);
}
-export async function signInWithGitHub(rememberMe: boolean): Promise<
- | {
- success: true;
- }
- | {
- success: false;
- message: string;
- }
-> {
+export async function signInWithGitHub(
+ rememberMe: boolean,
+): Promise {
return signInWithProvider(githubProvider, rememberMe);
}
@@ -275,15 +253,7 @@ export async function signUp(
name: string,
email: string,
password: string,
-): Promise<
- | {
- success: true;
- }
- | {
- success: false;
- message: string;
- }
-> {
+): Promise {
if (!isAuthAvailable()) {
return { success: false, message: "Authentication uninitialized" };
}
diff --git a/frontend/src/ts/collections/inbox.ts b/frontend/src/ts/collections/inbox.ts
index e9958178b482..4ca003694493 100644
--- a/frontend/src/ts/collections/inbox.ts
+++ b/frontend/src/ts/collections/inbox.ts
@@ -11,9 +11,9 @@ import { Accessor, createSignal } from "solid-js";
import Ape from "../ape";
import { queryClient } from "../queries";
import { baseKey } from "../queries/utils/keys";
-import { isLoggedIn } from "../signals/core";
+import { isLoggedIn } from "../states/core";
import { flushDebounceStrategy } from "./utils/flushDebounceStrategy";
-import { showErrorNotification } from "../stores/notifications";
+import { showErrorNotification } from "../states/notifications";
export const flushStrategy = flushDebounceStrategy({ maxWait: 1000 * 60 * 5 });
diff --git a/frontend/src/ts/commandline/commandline-metadata.ts b/frontend/src/ts/commandline/commandline-metadata.ts
index 7456615f7f39..a1cdb9c2d1a2 100644
--- a/frontend/src/ts/commandline/commandline-metadata.ts
+++ b/frontend/src/ts/commandline/commandline-metadata.ts
@@ -7,7 +7,7 @@ import { isAuthenticated } from "../firebase";
import { areUnsortedArraysEqual } from "../utils/arrays";
import Config from "../config";
import { get as getTypingSpeedUnit } from "../utils/typing-speed-units";
-import { getActivePage } from "../signals/core";
+import { getActivePage } from "../states/core";
import { Fonts } from "../constants/fonts";
import { KnownFontName } from "@monkeytype/schemas/fonts";
import * as UI from "../ui";
diff --git a/frontend/src/ts/commandline/commandline.ts b/frontend/src/ts/commandline/commandline.ts
index 75b94fb1f316..61959f04b023 100644
--- a/frontend/src/ts/commandline/commandline.ts
+++ b/frontend/src/ts/commandline/commandline.ts
@@ -5,14 +5,14 @@ import * as AnalyticsController from "../controllers/analytics-controller";
import * as ThemeController from "../controllers/theme-controller";
import { clearFontPreview } from "../ui";
import AnimatedModal, { ShowOptions } from "../utils/animated-modal";
-import { showNoticeNotification } from "../stores/notifications";
+import { showNoticeNotification } from "../states/notifications";
import * as OutOfFocus from "../test/out-of-focus";
import {
getActivePage,
getCommandlineSubgroup,
setCommandlineSubgroup,
-} from "../signals/core";
-import { showLoaderBar, hideLoaderBar } from "../signals/loader-bar";
+} from "../states/core";
+import { showLoaderBar, hideLoaderBar } from "../states/loader-bar";
import { Command, CommandsSubgroup, CommandWithValidation } from "./types";
import { areSortedArraysEqual, areUnsortedArraysEqual } from "../utils/arrays";
import { parseIntOptional } from "../utils/numbers";
@@ -28,7 +28,7 @@ import {
hideModal as storeHideModal,
hideModalAndClearChain as storeClearChain,
isModalOpen,
-} from "../stores/modals";
+} from "../states/modals";
import { ValidationResult } from "../types/validation";
type CommandlineMode = "search" | "input";
diff --git a/frontend/src/ts/commandline/lists.ts b/frontend/src/ts/commandline/lists.ts
index 6466518c6765..0a59523967b3 100644
--- a/frontend/src/ts/commandline/lists.ts
+++ b/frontend/src/ts/commandline/lists.ts
@@ -25,7 +25,7 @@ import {
showErrorNotification,
showSuccessNotification,
clearAllNotifications,
-} from "../stores/notifications";
+} from "../states/notifications";
import * as VideoAdPopup from "../popups/video-ad-popup";
import * as ShareTestSettingsPopup from "../modals/share-test-settings";
import * as TestStats from "../test/test-stats";
diff --git a/frontend/src/ts/commandline/lists/bail-out.ts b/frontend/src/ts/commandline/lists/bail-out.ts
index d73fbdae9736..c750312f2ac6 100644
--- a/frontend/src/ts/commandline/lists/bail-out.ts
+++ b/frontend/src/ts/commandline/lists/bail-out.ts
@@ -2,7 +2,7 @@ import Config from "../../config";
import * as CustomText from "../../test/custom-text";
import * as TestLogic from "../../test/test-logic";
import * as TestState from "../../test/test-state";
-import * as CustomTextState from "../../states/custom-text-name";
+import * as CustomTextState from "../../legacy-states/custom-text-name";
import { Command, CommandsSubgroup } from "../types";
function canBailOut(): boolean {
diff --git a/frontend/src/ts/commandline/lists/custom-background.ts b/frontend/src/ts/commandline/lists/custom-background.ts
index 3033920f415e..3f4624410657 100644
--- a/frontend/src/ts/commandline/lists/custom-background.ts
+++ b/frontend/src/ts/commandline/lists/custom-background.ts
@@ -3,7 +3,8 @@ import { buildCommandForConfigKey } from "../util";
import FileStorage from "../../utils/file-storage";
import { applyCustomBackground } from "../../controllers/theme-controller";
import { updateUI } from "../../elements/settings/custom-background-picker";
-import { showNoticeNotification } from "../../stores/notifications";
+import { showNoticeNotification } from "../../states/notifications";
+import Config, { setConfig } from "../../config";
const fromMeta = buildCommandForConfigKey("customBackground");
@@ -69,16 +70,19 @@ const customBackgroundCommand: Command = {
},
},
{
- id: "removeLocalBackground",
- display: "Remove local background",
+ id: "removeCustomBackground",
+ display: "Remove custom background",
icon: "fa-trash",
- alias: "remove background",
available: async (): Promise => {
- return await FileStorage.hasFile("LocalBackgroundFile");
+ return (
+ (await FileStorage.hasFile("LocalBackgroundFile")) ||
+ Config.customBackground !== ""
+ );
},
exec: async (): Promise => {
try {
await FileStorage.deleteFile("LocalBackgroundFile");
+ setConfig("customBackground", "");
await applyCustomBackground();
await updateUI();
} catch (e) {
diff --git a/frontend/src/ts/commandline/lists/font-family.ts b/frontend/src/ts/commandline/lists/font-family.ts
index 0fe501e0e275..3ef441151cda 100644
--- a/frontend/src/ts/commandline/lists/font-family.ts
+++ b/frontend/src/ts/commandline/lists/font-family.ts
@@ -3,7 +3,7 @@ import { buildCommandForConfigKey } from "../util";
import FileStorage from "../../utils/file-storage";
import { applyFontFamily } from "../../controllers/theme-controller";
import { updateUI } from "../../elements/settings/custom-font-picker";
-import { showNoticeNotification } from "../../stores/notifications";
+import { showNoticeNotification } from "../../states/notifications";
import Config, { setConfig } from "../../config";
const fromMeta = buildCommandForConfigKey("fontFamily");
diff --git a/frontend/src/ts/commandline/lists/quote-favorites.ts b/frontend/src/ts/commandline/lists/quote-favorites.ts
index 62d6ba802395..adb329968f6a 100644
--- a/frontend/src/ts/commandline/lists/quote-favorites.ts
+++ b/frontend/src/ts/commandline/lists/quote-favorites.ts
@@ -3,9 +3,9 @@ import QuotesController, { Quote } from "../../controllers/quotes-controller";
import {
showErrorNotification,
showSuccessNotification,
-} from "../../stores/notifications";
+} from "../../states/notifications";
import { isAuthenticated } from "../../firebase";
-import { showLoaderBar, hideLoaderBar } from "../../signals/loader-bar";
+import { showLoaderBar, hideLoaderBar } from "../../states/loader-bar";
import * as TestWords from "../../test/test-words";
import { Command } from "../types";
diff --git a/frontend/src/ts/commandline/lists/result-screen.ts b/frontend/src/ts/commandline/lists/result-screen.ts
index e88151b5d5bd..0ab77c979907 100644
--- a/frontend/src/ts/commandline/lists/result-screen.ts
+++ b/frontend/src/ts/commandline/lists/result-screen.ts
@@ -4,7 +4,7 @@ import * as PractiseWordsModal from "../../modals/practise-words";
import {
showErrorNotification,
showSuccessNotification,
-} from "../../stores/notifications";
+} from "../../states/notifications";
import * as TestInput from "../../test/test-input";
import * as TestState from "../../test/test-state";
import * as TestWords from "../../test/test-words";
diff --git a/frontend/src/ts/components/common/AnimatedModal.tsx b/frontend/src/ts/components/common/AnimatedModal.tsx
index d9a72973981f..e7af3d3d599d 100644
--- a/frontend/src/ts/components/common/AnimatedModal.tsx
+++ b/frontend/src/ts/components/common/AnimatedModal.tsx
@@ -12,7 +12,7 @@ import {
ModalId,
isModalOpen,
isModalChained,
-} from "../../stores/modals";
+} from "../../states/modals";
import { cn } from "../../utils/cn";
import { applyReducedMotion } from "../../utils/misc";
diff --git a/frontend/src/ts/components/common/AsyncContent.tsx b/frontend/src/ts/components/common/AsyncContent.tsx
index 49da2e478ce7..947854c28bd6 100644
--- a/frontend/src/ts/components/common/AsyncContent.tsx
+++ b/frontend/src/ts/components/common/AsyncContent.tsx
@@ -9,7 +9,7 @@ import {
Switch,
} from "solid-js";
-import { showErrorNotification } from "../../stores/notifications";
+import { showErrorNotification } from "../../states/notifications";
import { createErrorMessage } from "../../utils/error";
import { typedKeys } from "../../utils/misc";
import { Conditional } from "./Conditional";
diff --git a/frontend/src/ts/components/common/Balloon.tsx b/frontend/src/ts/components/common/Balloon.tsx
index 50d65efec039..8c122238950b 100644
--- a/frontend/src/ts/components/common/Balloon.tsx
+++ b/frontend/src/ts/components/common/Balloon.tsx
@@ -18,21 +18,20 @@ type Props = ParentProps &
};
export function buildBalloonHtmlProperties(
- props: BalloonProps | undefined,
+ options: BalloonProps | undefined,
): Record {
- // oxlint-disable-next-line solid/reactivity just a util - consumer is responsible for reactivity
- if (props === undefined || props.text === undefined || props.text === "") {
+ if (
+ options === undefined ||
+ options.text === undefined ||
+ options.text === ""
+ ) {
return {};
}
return {
- // oxlint-disable-next-line solid/reactivity just a util - consumer is responsible for reactivity
- "aria-label": props.text,
- // oxlint-disable-next-line solid/reactivity
- "data-balloon-pos": props.position ?? "up",
- // oxlint-disable-next-line solid/reactivity
- ...(props.break ? { "data-balloon-break": "" } : {}),
- // oxlint-disable-next-line solid/reactivity
- ...(props.length ? { "data-balloon-length": props.length } : {}),
+ "aria-label": options.text,
+ "data-balloon-pos": options.position ?? "up",
+ ...(options.break ? { "data-balloon-break": "" } : {}),
+ ...(options.length ? { "data-balloon-length": options.length } : {}),
};
}
diff --git a/frontend/src/ts/components/common/Button.tsx b/frontend/src/ts/components/common/Button.tsx
index 03c7aebb0725..545a4209a990 100644
--- a/frontend/src/ts/components/common/Button.tsx
+++ b/frontend/src/ts/components/common/Button.tsx
@@ -14,13 +14,15 @@ type BaseProps = {
balloon?: BalloonProps;
"router-link"?: true;
onClick?: () => void;
+ type?: HTMLButtonElement["type"];
onMouseEnter?: () => void;
onMouseLeave?: () => void;
dataset?: Record;
active?: boolean;
};
-type ButtonProps = BaseProps & {
+export type ButtonProps = BaseProps & {
+ type?: "button" | "submit" | "reset";
href?: never;
sameTarget?: true;
disabled?: boolean;
@@ -30,6 +32,7 @@ type AnchorProps = BaseProps & {
href: string;
// onClick?: never;
disabled?: never;
+ type?: never;
};
export function Button(props: ButtonProps | AnchorProps): JSXElement {
@@ -107,7 +110,8 @@ export function Button(props: ButtonProps | AnchorProps): JSXElement {
}
else={
+ }
+ else={
+