diff --git a/packages/repl/src/components/settings/login/Login.tsx b/packages/repl/src/components/settings/login/Login.tsx index fec82e2..3298296 100644 --- a/packages/repl/src/components/settings/login/Login.tsx +++ b/packages/repl/src/components/settings/login/Login.tsx @@ -1,9 +1,9 @@ import type { mtcute, TelegramAccount } from 'mtcute-repl-worker/client' import type { Setter } from 'solid-js' import { unknownToError } from '@fuman/utils' -import { LucideChevronRight, MessageSquareMore } from 'lucide-solid' +import { LucideChevronRight, LucideLockKeyhole, MessageSquareMore } from 'lucide-solid' import { workerInvoke, workerOn } from 'mtcute-repl-worker/client' -import { createEffect, createSignal, For, Match, onCleanup, onMount, Show, Switch } from 'solid-js' +import { createSignal, For, Match, onCleanup, onMount, Show, Switch } from 'solid-js' import { Button } from '../../../lib/components/ui/button.tsx' import { OTPField, OTPFieldGroup, OTPFieldInput, OTPFieldSlot } from '../../../lib/components/ui/otp-field.tsx' import { Spinner } from '../../../lib/components/ui/spinner.tsx' @@ -81,7 +81,7 @@ function QrLoginStep(props: StepProps<'qr'>) { /> ) : } -
    +
    1. Open Telegram on your phone
    2. Go to @@ -147,7 +147,7 @@ function PhoneNumberStep(props: StepProps<'phone'>) {

      Log in with phone number

      -
      +
      Please confirm your country code
      and enter your phone number @@ -177,7 +177,7 @@ function PhoneNumberStep(props: StepProps<'phone'>) { {error()}
      -
      +
      or, {' '} ) { const [error, setError] = createSignal() const [loading, setLoading] = createSignal(false) const [countdown, setCountdown] = createSignal(0) - const [inputRef, setInputRef] = createSignal() const abortController = new AbortController() const handleSubmit = async () => { @@ -269,9 +268,9 @@ function OtpStep(props: StepProps<'otp'>) { setCountdown(0) } }, 1000) + onCleanup(() => clearInterval(interval)) }) - createEffect(() => inputRef()?.focus()) const description = () => { switch (props.ctx.code.type) { @@ -297,19 +296,6 @@ function OtpStep(props: StepProps<'otp'>) { } } - const [innerInputRef, setInnerInputRef] = createSignal() - - onMount(() => { - const handleKeyDown = (e: KeyboardEvent) => { - if (e.key >= '0' && e.key <= '9') { - innerInputRef()?.focus() - } - } - - window.addEventListener('keydown', handleKeyDown) - onCleanup(() => window.removeEventListener('keydown', handleKeyDown)) - }) - return (
      @@ -323,7 +309,7 @@ function OtpStep(props: StepProps<'otp'>) { Wrong number?
      -
      +
      {description()}
      @@ -343,7 +329,7 @@ function OtpStep(props: StepProps<'otp'>) { handleSubmit() } }} - ref={(e) => { setInputRef(e); setInnerInputRef(e) }} + ref={props.ctx.setInputRef} /> {error()} @@ -358,7 +344,7 @@ function OtpStep(props: StepProps<'otp'>) { > { setInputRef(e); setInnerInputRef(e) }} + ref={props.ctx.setInputRef} onKeyPress={(e) => { if (e.key === 'Enter') { handleSubmit() @@ -377,7 +363,7 @@ function OtpStep(props: StepProps<'otp'>) { {error() && ( -
      {error()}
      +
      {error()}
      )} @@ -400,10 +386,24 @@ function OtpStep(props: StepProps<'otp'>) { } function PasswordStep(props: StepProps<'password'>) { + const [inputRef, setInputRef] = createSignal() const [password, setPassword] = createSignal('') const [error, setError] = createSignal() const [loading, setLoading] = createSignal(false) - const [inputRef, setInputRef] = createSignal() + + onMount(() => { + const pasteHandler = () => { + if (document.activeElement !== inputRef()) { + inputRef()?.focus() + } + } + + window.addEventListener('paste', pasteHandler) + + onCleanup(() => { + window.removeEventListener('paste', pasteHandler) + }) + }) const abortController = new AbortController() onCleanup(() => abortController.abort()) @@ -411,6 +411,7 @@ function PasswordStep(props: StepProps<'password'>) { const handleSubmit = async () => { if (!password()) { setError('Password is required') + inputRef()?.focus() return } @@ -427,49 +428,51 @@ function PasswordStep(props: StepProps<'password'>) { setLoading(false) setError(unknownToError(e).message) } + + inputRef()?.focus() } - createEffect(() => inputRef()?.focus()) return (
      +

      2FA password

      -
      +
      Your account is protected with an additional password.
      -
      +
      Password - - setPassword(e.currentTarget.value)} - disabled={loading()} - ref={setInputRef} - onKeyPress={(e) => { - if (e.key === 'Enter') { - handleSubmit() - } - }} - /> - +
      + + setPassword(e.currentTarget.value)} + disabled={loading()} + ref={(e) => { props.ctx.setInputRef(e); setInputRef(e) }} + onKeyPress={(e) => { + if (e.key === 'Enter') { + handleSubmit() + } + }} + /> + + +
      {error()}
      - -
      - -
      ) @@ -480,9 +483,9 @@ function DoneStep(props: StepProps<'done'>) {
      -
      +
      Welcome, {' '} {props.ctx.account.name} @@ -508,6 +511,26 @@ export function LoginForm(props: { const [inputRef, setInputRef] = createSignal() + onMount(() => { + const pasteHandler = () => { + if (document.activeElement !== inputRef()) { + inputRef()?.focus() + } + } + + const handleKeyDown = () => { + inputRef()?.focus() + } + + window.addEventListener('paste', pasteHandler) + window.addEventListener('keydown', handleKeyDown) + + onCleanup(() => { + window.removeEventListener('paste', pasteHandler) + window.removeEventListener('keydown', handleKeyDown) + }) + }) + return (
      inputRef()?.focus()} mode="outin"> diff --git a/packages/repl/src/components/settings/login/PhoneInput.tsx b/packages/repl/src/components/settings/login/PhoneInput.tsx index a01c06f..3b1cc95 100644 --- a/packages/repl/src/components/settings/login/PhoneInput.tsx +++ b/packages/repl/src/components/settings/login/PhoneInput.tsx @@ -29,26 +29,11 @@ interface PhoneInputProps { } export function PhoneInput(props: PhoneInputProps) { + let inputRef: HTMLInputElement | undefined const [countriesList, setCountriesList] = createSignal([]) const [chosenCode, setChosenCode] = createSignal() const [inputValue, setInputValue] = createSignal('+') - onMount(async () => { - const { countries, countryByIp } = await workerInvoke('telegram', 'loadCountries', { accountId: props.accountId }) - setCountriesList(countries) - - if (inputValue() === '+') { - // guess the country code - for (const country of countries) { - if (country.iso2 === countryByIp) { - setChosenCode(mapCountryCode(country, country.countryCodes[0])) - setInputValue(`+${country.countryCodes[0].countryCode} `) - break - } - } - } - }) - const handleInput = (e: InputEvent) => { const el = e.currentTarget as HTMLInputElement const value = el.value @@ -155,6 +140,26 @@ export function PhoneInput(props: PhoneInputProps) { } } + onMount(async () => { + const { countries, countryByIp } = await workerInvoke('telegram', 'loadCountries', { accountId: props.accountId }) + setCountriesList(countries) + + if (chosenCode() === undefined) { + handleInput({ currentTarget: inputRef } as any) + } + + if (inputValue() === '+') { + // guess the country code + for (const country of countries) { + if (country.iso2 === countryByIp) { + setChosenCode(mapCountryCode(country, country.countryCodes[0])) + setInputValue(`+${country.countryCodes[0].countryCode} `) + break + } + } + } + }) + const handleKeyPress = (e: KeyboardEvent) => { if (e.key === 'Enter' && chosenCode() !== undefined) { props.onSubmit?.() @@ -180,7 +185,10 @@ export function PhoneInput(props: PhoneInputProps) { onKeyPress={handleKeyPress} autocomplete="off" disabled={props.disabled} - ref={props.ref} + ref={(e: HTMLInputElement) => { + inputRef = e + props.ref?.(e) + }} /> )