Skip to content

Commit

Permalink
Submit on enter
Browse files Browse the repository at this point in the history
  • Loading branch information
tarrencev committed Jan 22, 2025
1 parent f4f6c7f commit d2f16ee
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 12 deletions.
13 changes: 11 additions & 2 deletions packages/keychain/src/components/ErrorAlert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ export function ErrorAlert({
isExpanded = false,
allowToggle = false,
copyText,
className,
}: {
title: string;
description?: string | ReactElement;
variant?: string;
isExpanded?: boolean;
allowToggle?: boolean;
copyText?: string;
className?: string;
}) {
const [copied, setCopied] = useState(false);

Expand Down Expand Up @@ -69,6 +71,7 @@ export function ErrorAlert({
type="single"
collapsible={collapsible}
defaultValue={isExpanded ? "item-1" : undefined}
className={className}
>
<AccordionItem
value="item-1"
Expand Down Expand Up @@ -119,9 +122,11 @@ export function ErrorAlert({
export function ControllerErrorAlert({
error,
isPaymaster = false,
className,
}: {
error: ControllerError | Error;
isPaymaster?: boolean;
className?: string;
}) {
let title = "An error occurred";
let description: string | React.ReactElement = error.message;
Expand All @@ -140,6 +145,7 @@ export function ControllerErrorAlert({
variant={variant}
isExpanded={isExpanded}
copyText={copyText}
className={className}
/>
);
}
Expand Down Expand Up @@ -196,7 +202,8 @@ export function ControllerErrorAlert({
break;
case ErrorCode.DeviceGetAssertion:
title = "Authentication Error";
description = "The authentication request timed out or was cancelled. Please try again.";
description =
"The authentication request timed out or was cancelled. Please try again.";
isExpanded = true;
break;
case ErrorCode.DeviceBadAssertion:
Expand All @@ -211,7 +218,8 @@ export function ControllerErrorAlert({
break;
case ErrorCode.DeviceOrigin:
title = "Security Error";
description = "Invalid security origin. Please ensure you're using a secure connection.";
description =
"Invalid security origin. Please ensure you're using a secure connection.";
isExpanded = true;
break;
case ErrorCode.PaymasterExecutionTimeNotReached:
Expand Down Expand Up @@ -324,6 +332,7 @@ export function ControllerErrorAlert({
variant={variant}
isExpanded={isExpanded}
copyText={copyText}
className={className}
/>
);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/keychain/src/components/connect/CreateSession.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export function CreateSession({
</div>
)}

{error && <ControllerErrorAlert error={error} />}
{error && <ControllerErrorAlert className="mb-3" error={error} />}

<div className="flex items-center gap-4">
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ interface CreateControllerViewProps {
onUsernameFocus: () => void;
onUsernameClear: () => void;
onSubmit: () => void;
onKeyDown: (e: React.KeyboardEvent) => void;
isInAppBrowser?: boolean;
}

Expand All @@ -39,6 +40,7 @@ export function CreateControllerView({
onUsernameFocus,
onUsernameClear,
onSubmit,
onKeyDown,
}: CreateControllerViewProps) {
return (
<Container
Expand All @@ -53,8 +55,9 @@ export function CreateControllerView({
>
<form
className="flex flex-col flex-1"
onKeyDown={(e) => {
if (e.key === "Enter") e.preventDefault();
onSubmit={(e) => {
e.preventDefault();
onSubmit();
}}
>
<Content className="gap-0">
Expand All @@ -72,6 +75,7 @@ export function CreateControllerView({
onChange={(e) => {
onUsernameChange(e.target.value.toLowerCase());
}}
onKeyDown={onKeyDown}
isLoading={validation.status === "validating"}
disabled={isLoading}
onClear={onUsernameClear}
Expand Down Expand Up @@ -112,9 +116,9 @@ export function CreateControllerView({
<Legal />

<Button
type="submit"
isLoading={isLoading}
disabled={validation.status !== "valid"}
onClick={onSubmit}
>
{validation.exists ? "login" : "sign up"}
</Button>
Expand Down Expand Up @@ -152,14 +156,29 @@ export function CreateController({
const hasLoggedFocus = useRef(false);
const hasLoggedChange = useRef(false);
const theme = useControllerTheme();
const pendingSubmitRef = useRef(false);

const [usernameField, setUsernameField] = useState({
value: "",
error: undefined,
});

const { debouncedValue: username } = useDebounce(usernameField.value, 100);
const validation = useUsernameValidation(username);
// Debounce validation quickly to reduce latency
const { debouncedValue: validationUsername } = useDebounce(
usernameField.value,
25,
);

const validation = useUsernameValidation(validationUsername);
// Debounce the validation result rather than the input value
const { debouncedValue: debouncedValidation } = useDebounce(validation, 200);

useEffect(() => {
if (pendingSubmitRef.current && debouncedValidation.status === "valid") {
pendingSubmitRef.current = false;
handleFormSubmit();
}
}, [debouncedValidation.status]);

const { isLoading, error, setError, handleSubmit } = useCreateController({
onCreated,
Expand Down Expand Up @@ -208,21 +227,37 @@ export function CreateController({
if (!usernameField.value) {
return;
}
handleSubmit(usernameField.value, !!validation.exists);

if (validation.status === "validating") {
pendingSubmitRef.current = true;
return;
}

if (validation.status === "valid") {
handleSubmit(usernameField.value, !!validation.exists);
}
};

const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === "Enter") {
e.preventDefault();
handleFormSubmit();
}
};

return (
<CreateControllerView
theme={theme}
usernameField={usernameField}
validation={validation}
validation={debouncedValidation}
isLoading={isLoading}
error={error}
isInAppBrowser={isInApp}
onUsernameChange={handleUsernameChange}
onUsernameFocus={handleUsernameFocus}
onUsernameClear={handleUsernameClear}
onSubmit={handleFormSubmit}
onKeyDown={handleKeyDown}
/>
);
}
15 changes: 13 additions & 2 deletions packages/keychain/src/hooks/upgrade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,18 @@ export const useUpgrade = (controller?: Controller): UpgradeInterface => {
const [isUpgrading, setIsUpgrading] = useState<boolean>(false);
const [current, setCurrent] = useState<ControllerVersionInfo>();
const [calls, setCalls] = useState<JsCall[]>([]);
const [syncedControllerAddress, setSyncedControllerAddress] = useState<string>();

useEffect(() => {
if (!controller) {
return;
}

// Skip if we already synced this controller
if (syncedControllerAddress === controller.address) {
return;
}

setIsSynced(false);

controller
Expand All @@ -89,6 +96,7 @@ export const useUpgrade = (controller?: Controller): UpgradeInterface => {

setCurrent(current);
setAvailable(current?.version !== LATEST_CONTROLLER.version);
setSyncedControllerAddress(controller.address);
})
.catch((e) => {
if (e.message.includes("Contract not found")) {
Expand All @@ -104,8 +112,11 @@ export const useUpgrade = (controller?: Controller): UpgradeInterface => {
setError(e);
}
})
.finally(() => setIsSynced(true));
}, [controller]);
.finally(() => {
setSyncedControllerAddress(controller.address);
setIsSynced(true);
});
}, [controller, syncedControllerAddress]);

useEffect(() => {
if (!controller || !LATEST_CONTROLLER) {
Expand Down

0 comments on commit d2f16ee

Please sign in to comment.