lodash-es#find TypeScript Examples
The following examples show how to use
lodash-es#find.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: App.tsx From yasd with MIT License | 4 votes |
App: React.FC = () => {
const { t, i18n } = useTranslation()
const [isNetworkModalOpen, setIsNetworkModalOpen] = useState(false)
const location = useLocation()
const history = useHistory()
const profileDispatch = useProfileDispatch()
const profile = useProfile()
const [hasInit, setHasInit] = useState(false)
const isCurrentVersionFetched = useRef(true)
const platformVersion = usePlatformVersion()
const onCloseApplication = useCallback(() => {
if (isRunInSurge()) {
store.remove(LastUsedProfile)
store.remove(ExistingProfiles)
}
window.location.replace('/')
}, [])
useEffect(
() => {
const existingProfiles = store.get(ExistingProfiles)
const lastId = store.get(LastUsedProfile)
const result = find<Profile>(existingProfiles, { id: lastId })
if (result) {
profileDispatch({
type: 'update',
payload: result,
})
}
setHasInit(true)
},
// eslint-disable-next-line
[],
)
useEffect(() => {
if (hasInit && !profile && location.pathname !== '/') {
history.replace('/')
}
}, [hasInit, history, location.pathname, profile])
useEffect(() => {
ReactGA.pageview(location.pathname)
}, [location.pathname])
useEffect(() => {
const language: string | null = store.get(LastUsedLanguage)
if (language && language !== i18n.language) {
i18n.changeLanguage(language)
}
}, [i18n])
useEffect(() => {
if (
!profile?.platform ||
!isCurrentVersionFetched.current ||
location.pathname === '/'
) {
return
}
httpClient
.request({
url: '/environment',
method: 'GET',
})
.then((res) => {
const currentPlatformVersion = res.headers['x-surge-version']
if (currentPlatformVersion !== platformVersion) {
profileDispatch({
type: 'updatePlatformVersion',
payload: {
platformVersion: currentPlatformVersion,
},
})
}
isCurrentVersionFetched.current = false
})
.catch((err) => {
console.error(err)
toast.error(t('common.surge_too_old'))
})
}, [location, platformVersion, profile?.platform, profileDispatch, t])
return (
<SWRConfig
value={{
onError: (error) => {
if (location.pathname !== '/') {
if (!error.response && error.request) {
// 无法连接服务器
setIsNetworkModalOpen(true)
}
}
},
refreshWhenOffline: true,
}}
>
<ScrollToTop />
<ToastContainer />
<NetworkErrorModal
reloadButton={isRunInSurge()}
isOpen={isNetworkModalOpen}
onClose={onCloseApplication}
/>
<NewVersionAlert />
<PageLayout>
<Switch>
<Route exact path="/">
{isRunInSurge() ? <SurgeLandingPage /> : <LandingPage />}
</Route>
<Route exact path="/home">
<IndexPage />
</Route>
<Route exact path="/policies">
<PoliciesPage />
</Route>
<Route exact path="/requests">
<RequestsPage />
</Route>
<Route exact path="/traffic">
<TrafficPage />
</Route>
<Route exact path="/modules">
<ModulesPage />
</Route>
<Route exact path="/scripting">
<ScriptingPage />
</Route>
<Route exact path="/scripting/evaluate">
<EvaluatePage />
</Route>
<Route exact path="/dns">
<DnsPage />
</Route>
<Route exact path="/devices">
<DevicesPage />
</Route>
<Route exact path="/profiles/current">
<ProfilePage />
</Route>
<Route path="*">
<Redirect to="/" />
</Route>
</Switch>
</PageLayout>
</SWRConfig>
)
}
Example #2
Source File: SetHostModal.tsx From yasd with MIT License | 4 votes |
SetHostModal: React.FC = () => {
const { t } = useTranslation()
const [existingProfiles, setExistingProfiles] = useState<Array<Profile>>([])
const { setModal } = useModal()
const currentProfile = useProfile()
const history = useHistory()
const selectProfile = useCallback(
(id: string) => {
const profile = find(existingProfiles, { id })
if (profile) {
store.set(LastUsedProfile, profile.id)
window.location.reload()
}
},
[existingProfiles],
)
useEffect(() => {
const storedExistingProfiles = store.get(ExistingProfiles)
if (storedExistingProfiles) {
setExistingProfiles(storedExistingProfiles)
}
}, [])
const showModal = () => {
setModal({
// eslint-disable-next-line react/display-name
children: ({ onClose }) => {
return (
<ModalWrapper>
<ModalHeader title={t('landing.history')} onClose={onClose} />
<div tw="bg-gray-100 divide-y divide-gray-200 rounded overflow-hidden">
{existingProfiles.map((profile) => {
return (
<div
key={profile.id}
tw="flex flex-row items-center hover:bg-gray-200"
>
{profile.id === currentProfile?.id && (
<Badge variant="success" tw="ml-3 text-xs md:text-sm">
{t('landing.current')}
</Badge>
)}
<div tw="flex-1">
<ProfileCell
profile={profile}
checkConnectivity
onClick={() => selectProfile(profile.id)}
/>
</div>
</div>
)
})}
</div>
<div tw="mt-4">
<Button
size="kilo"
variant="primary"
onClick={() => history.replace('/')}
>
{t('landing.add_new_host')}
</Button>
</div>
</ModalWrapper>
)
},
onClose() {
// noop
},
})
}
return (
<IconButton label={'change host'} tw="w-10 h-10 p-1" onClick={showModal}>
<Laptop />
</IconButton>
)
}
Example #3
Source File: Regular.tsx From yasd with MIT License | 4 votes |
Page: React.FC = () => {
const history = useHistory()
const protocol = window.location.protocol
const { isLoading, setIsLoading } = useAuthData()
const [existingProfiles, setExistingProfiles, getExistingProfiles] =
useSetState<Array<Profile>>([])
const profileDispatch = useProfileDispatch()
const { t } = useTranslation()
const {
getValues,
register,
handleSubmit,
control,
clearErrors,
setError,
reset,
formState: { errors },
} = useForm<RegularFormFields>({
defaultValues: {
keepCredential: false,
useTls: window.location.protocol === 'https:',
},
})
const addProfile = (config: Omit<Profile, 'id'>): Profile => {
const profile: Profile = {
...config,
id: uuid(),
}
const newProfiles = [profile, ...existingProfiles]
setExistingProfiles(newProfiles)
if (getValues('keepCredential')) {
store.set(ExistingProfiles, newProfiles)
store.set(LastUsedProfile, profile.id)
}
return profile
}
const selectProfile = (id: string) => {
getExistingProfiles().then((profiles) => {
const profile = find(profiles, { id })
if (profile) {
if (getValues('keepCredential')) {
store.set(LastUsedProfile, profile.id)
}
profileDispatch({
type: 'update',
payload: profile,
})
history.replace('/home')
}
})
}
const deleteProfile = (id: string) => {
const profiles = existingProfiles.filter((item) => item.id !== id)
setExistingProfiles(profiles)
store.set(ExistingProfiles, profiles)
}
const onSubmit = (data: RegularFormFields) => {
if (!data.name || !data.host || !data.port || !data.key) {
return
}
setIsLoading(true)
tryHost(data.useTls ? 'https:' : 'http:', data.host, data.port, data.key)
.then((res) => {
clearErrors()
const newProfile = addProfile({
name: data.name,
host: data.host,
port: Number(data.port),
key: data.key,
platform: res.platform,
platformVersion: res.platformVersion,
platformBuild: res.platformBuild,
tls: data.useTls,
})
reset()
setIsLoading(false)
selectProfile(newProfile.id)
})
.catch((err) => {
setError('key', {
type: 'invalid',
message: err.message,
})
setError('host', {
type: 'invalid',
})
setError('port', {
type: 'invalid',
})
console.error(err)
setIsLoading(false)
})
}
useEffect(() => {
const storedExistingProfiles = store.get(ExistingProfiles)
if (storedExistingProfiles) {
setExistingProfiles(storedExistingProfiles)
}
}, [setExistingProfiles])
return (
<div
css={css`
padding-bottom: calc(env(safe-area-inset-bottom) + 1.25rem);
`}
>
<Header />
<div tw="max-w-xs sm:max-w-sm md:max-w-md mx-auto">
<Heading size={'tera'}>{t('landing.add_new_host')}</Heading>
<div tw="bg-teal-100 border-t-4 border-teal-500 rounded-b text-teal-900 text-sm px-4 py-3 mb-4 shadow-md">
<p tw="leading-normal mb-2">
该功能仅 Surge iOS 4.4.0 和 Surge Mac 4.0.0 以上版本支持。
</p>
<p tw="leading-normal mb-4">
<a
href="https://manual.nssurge.com/others/http-api.html#configuration"
target="_blank"
rel="noreferrer"
tw="border-b border-solid border-teal-500"
>
? 开启方式
</a>
</p>
<p tw="leading-normal mb-2">
Surge Mac v4.0.6 (1280) 开始已支持开启 HTTPS API,故不再支持使用
yasd-helper。
</p>
</div>
<form onSubmit={handleSubmit(onSubmit)}>
<Input
type="text"
invalid={!!errors?.name}
validationHint={getValidationHint(
{
required: t('devices.err_required'),
},
errors?.name,
)}
label={t('landing.name')}
placeholder="Mac"
{...register('name', { required: true })}
/>
<Input
type="text"
invalid={!!errors?.host}
label={t('landing.host')}
placeholder="127.0.0.1"
validationHint={t('landing.host_tips')}
{...register('host', { required: true })}
/>
<Input
type="number"
invalid={!!errors?.port}
label={t('landing.port')}
placeholder="6171"
validationHint={getValidationHint(
{
required: t('devices.err_required'),
},
errors?.port,
)}
{...register('port', { required: true })}
/>
<Input
type="password"
invalid={!!errors?.key}
validationHint={getValidationHint(
{
required: t('devices.err_required'),
},
errors?.key,
)}
label={t('landing.key')}
placeholder="examplekey"
{...register('key', { required: true })}
/>
<div>
<Controller
name="useTls"
control={control}
render={({ field }) => (
<Checkbox
disabled={protocol === 'https:'}
checked={field.value}
onChange={field.onChange}
>
{t('landing.https')}
</Checkbox>
)}
/>
<Controller
name="keepCredential"
control={control}
render={({ field }) => (
<Checkbox checked={field.value} onChange={field.onChange}>
{t('landing.remember_me')}
</Checkbox>
)}
/>
</div>
<div tw="mt-6">
<LoadingButton
type="submit"
variant="primary"
stretch
isLoading={isLoading}
loadingLabel={t('landing.is_loading')}
>
{t('landing.confirm')}
</LoadingButton>
</div>
</form>
</div>
{existingProfiles.length > 0 && (
<div tw="max-w-xs sm:max-w-sm md:max-w-md mx-auto mt-10">
<Heading size={'mega'}>{t('landing.history')}</Heading>
<div tw="bg-gray-100 divide-y divide-gray-200 rounded overflow-hidden">
{existingProfiles.map((profile) => {
return (
<div key={profile.id} tw="hover:bg-gray-200">
<ProfileCell
profile={profile}
variant="left"
checkConnectivity
showDelete
onClick={() => selectProfile(profile.id)}
onDelete={() => deleteProfile(profile.id)}
/>
</div>
)
})}
</div>
</div>
)}
<div tw="max-w-xs sm:max-w-sm md:max-w-md mx-auto mt-10">
<Ad />
</div>
<div tw="mt-10">
<ChangeLanguage />
</div>
</div>
)
}
Example #4
Source File: Surge.tsx From yasd with MIT License | 4 votes |
Page: React.FC = () => {
const { t } = useTranslation()
const { isLoading, setIsLoading } = useAuthData()
const [existingProfiles, setExistingProfiles, getExistingProfiles] =
useSetState<Array<Profile>>([])
const profileDispatch = useProfileDispatch()
const profile = useProfile()
const history = useHistory()
const {
getValues,
register,
handleSubmit,
control,
clearErrors,
setError,
formState: { errors },
} = useForm<SurgeFormFields>({
defaultValues: {
keepCredential: false,
},
})
const addProfile = (config: Omit<Profile, 'id'>): Profile => {
const profile: Profile = {
...config,
id: uuid(),
}
const newProfiles = [profile, ...existingProfiles]
setExistingProfiles(newProfiles)
if (getValues('keepCredential')) {
store.set(ExistingProfiles, newProfiles)
store.set(LastUsedProfile, profile.id)
}
return profile
}
const selectProfile = (id: string) => {
getExistingProfiles().then((profiles) => {
const profile = find(profiles, { id })
if (profile) {
if (getValues('keepCredential')) {
store.set(LastUsedProfile, profile.id)
}
profileDispatch({
type: 'update',
payload: profile,
})
}
})
}
const getHost: () => {
protocol: string
hostname: string
port: string
} = () => {
const protocol = window.location.protocol
if (process.env.NODE_ENV === 'production') {
return {
protocol,
hostname: window.location.hostname,
port: window.location.port,
}
}
return {
protocol: process.env.REACT_APP_PROTOCOL as string,
hostname: process.env.REACT_APP_HOST as string,
port: process.env.REACT_APP_PORT as string,
}
}
const onSubmit = (data: SurgeFormFields) => {
if (!data.key) {
return
}
const { hostname, port, protocol } = getHost()
setIsLoading(true)
tryHost(protocol, hostname, port, data.key)
.then((res) => {
clearErrors()
const newProfile = addProfile({
name: res.name || 'Surge for Mac',
host: hostname,
port: Number(port),
key: data.key,
platform: res.platform,
platformVersion: res.platformVersion,
platformBuild: res.platformBuild,
tls: protocol === 'https:',
})
setIsLoading(false)
selectProfile(newProfile.id)
})
.catch((err) => {
setError('key', {
type: 'invalid',
message: err.message,
})
console.error(err)
setIsLoading(false)
})
}
useEffect(() => {
const storedExistingProfiles = store.get(ExistingProfiles)
const lastId = store.get(LastUsedProfile)
if (storedExistingProfiles) {
const result = find<Profile>(storedExistingProfiles, { id: lastId })
setExistingProfiles(storedExistingProfiles)
if (result) {
profileDispatch({
type: 'update',
payload: result,
})
}
}
}, [profileDispatch, setExistingProfiles])
useEffect(() => {
if (profile) {
history.replace('/home')
}
}, [profile, history])
return (
<div
css={css`
padding-bottom: calc(env(safe-area-inset-bottom) + 1.25rem);
`}
>
<Header />
<div tw="max-w-xs sm:max-w-sm md:max-w-md mx-auto">
<Heading size={'tera'}>{t('landing.login')}</Heading>
<form onSubmit={handleSubmit(onSubmit)}>
<Input
type="password"
invalid={!!errors?.key}
validationHint={getValidationHint(
{
required: t('devices.err_required'),
},
errors?.key,
)}
label={t('landing.key')}
placeholder="examplekey"
{...register('key', { required: true })}
/>
<div>
<Controller
name="keepCredential"
control={control}
render={({ field }) => (
<Checkbox checked={field.value} onChange={field.onChange}>
{t('landing.remember_me')}
</Checkbox>
)}
/>
</div>
<div tw="mt-6">
<LoadingButton
type="submit"
variant="primary"
stretch
isLoading={isLoading}
loadingLabel={t('landing.is_loading')}
>
{t('landing.confirm')}
</LoadingButton>
</div>
</form>
</div>
<div tw="mt-10">
<ChangeLanguage />
</div>
</div>
)
}