Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: proxy page style #47

Merged
merged 1 commit into from Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/components/Collpase.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { JSX, ParentComponent } from 'solid-js'
import { twMerge } from 'tailwind-merge'

type Props = {
title: JSX.Element
content: JSX.Element
isOpen: boolean | undefined
onCollapse: (collapsed: boolean) => void
}

const Collapse: ParentComponent<Props> = (props) => {
const { title, content, onCollapse } = props

const getCollapseClassName = () => {
return props.isOpen ? 'collapse-open' : 'collapse-close'
}
const getCollapseContentClassName = () => {
return props.isOpen ? 'opacity-100' : 'opacity-0 scale-y-0'
}

return (
<div
class={twMerge(
getCollapseClassName(),
'collapse collapse-arrow border-secondary bg-base-200 p-1',
)}
>
<div
class={'collapse-title text-xl font-medium'}
onClick={() => onCollapse(!props.isOpen)}
>
{title}
</div>
<div
class={twMerge(
getCollapseContentClassName(),
'collapse-content grid grid-cols-1 gap-2 overflow-hidden transition-opacity duration-1000 sm:grid-cols-3 lg:grid-cols-5',
)}
>
{content}
</div>
</div>
)
}

export default Collapse
36 changes: 36 additions & 0 deletions src/components/ProxyNodeCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { twMerge } from 'tailwind-merge'
import { useProxies } from '~/signals/proxies'

export default (props: {
proxyName: string
isSelected?: boolean
onClick?: () => void
}) => {
const { proxyName, isSelected, onClick } = props
const { delayMap } = useProxies()
const Delay = (proxyname: string) => {
const delay = delayMap()[proxyname]

if (typeof delay !== 'number' || delay === 0) {
return ''
}

return <span>{delay}ms</span>
}

return (
<div
class={twMerge(
isSelected
? 'border-primary bg-success-content text-success'
: 'border-secondary',
onClick ? 'cursor-pointer' : '',
'card card-bordered card-compact m-1 flex-row justify-between border-secondary p-4',
)}
onClick={() => onClick?.()}
>
<span class="mr-2 overflow-hidden whitespace-nowrap">{proxyName}</span>
<span>{Delay(proxyName)}</span>
</div>
)
}
151 changes: 67 additions & 84 deletions src/pages/Proxies.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,23 @@
import { IconBrandSpeedtest } from '@tabler/icons-solidjs'
import { For, createSignal, onMount } from 'solid-js'
import { twMerge } from 'tailwind-merge'
import Collapse from '~/components/Collpase'
import ProxyNodeCard from '~/components/ProxyNodeCard'
import { useProxies } from '~/signals/proxies'
import type { Proxy } from '~/types'

export default () => {
const {
proxies,
proxyProviders,
delayMap,
updateProxy,
setProxiesByProxyName,
delayTestByProxyGroupName,
} = useProxies()
const [collapseMap, setCollapseMap] = createSignal<Record<string, boolean>>(

const [collapsedMap, setCollapsedMap] = createSignal<Record<string, boolean>>(
{},
)

const renderDelay = (proxyname: string) => {
const delay = delayMap()[proxyname]

if (typeof delay !== 'number' || delay === 0) {
return ''
}

return <span>{delay}ms</span>
}

onMount(async () => {
await updateProxy()
})
Expand All @@ -35,65 +26,59 @@ export default () => {
setProxiesByProxyName(proxy, proxyName)
}

const onCollapseTitleClick = (name: string) => {
const cMap = collapseMap()

cMap[name] = !cMap[name]
setCollapseMap({ ...cMap })
}

const onSpeedTestClick = (e: MouseEvent, name: string) => {
e.stopPropagation()
delayTestByProxyGroupName(name)
}

const getCollapseClassName = (name: string) => {
return collapseMap()[name] ? 'collapse-open' : 'collapse-close'
}

return (
<div class="flex flex-col gap-4">
<div>
<h1 class="pb-4 text-lg font-semibold">Proxies</h1>

<div class="grid grid-cols-1 gap-2 sm:grid-cols-1">
<For each={proxies()}>
{(proxy) => (
<div
class={twMerge(
getCollapseClassName(proxy.name),
'collapse collapse-arrow border-secondary bg-base-200 p-4',
)}
>
<div
class="collapse-title flex h-10 items-center text-xl font-medium"
onClick={() => onCollapseTitleClick(proxy.name)}
>
{proxy.name} {proxy.type}
<IconBrandSpeedtest
class="m-4 cursor-pointer"
onClick={(e) => onSpeedTestClick(e, proxy.name)}
/>
</div>
<div class="collapse-content grid grid-cols-1 gap-2 sm:grid-cols-3 lg:grid-cols-5">
<For each={proxy.all}>
{(proxyName) => (
<div
class={twMerge(
proxy.now === proxyName
? 'border-primary bg-success-content text-success'
: 'border-secondary',
'card card-bordered card-compact m-1 cursor-pointer flex-row justify-between p-4',
)}
onClick={() => onProxyNodeClick(proxy, proxyName)}
>
{proxyName} {renderDelay(proxyName)}
</div>
)}
</For>
</div>
</div>
)}
{(proxy) => {
const title = (
<>
<div class="flex items-center">
<span class="mr-3">{proxy.name}</span>
<IconBrandSpeedtest
class="cursor-pointer"
onClick={(e) => onSpeedTestClick(e, proxy.name)}
/>
</div>
<div class="text-sm text-slate-500">
{proxy.type} :: {proxy.now}
</div>
</>
)
const content = (
<For each={proxy.all}>
{(proxyName) => (
<ProxyNodeCard
proxyName={proxyName}
isSelected={proxy.now === proxyName}
onClick={() => onProxyNodeClick(proxy, proxyName)}
/>
)}
</For>
)

return (
<Collapse
isOpen={collapsedMap()[`group-${proxy.name}`]}
title={title}
content={content}
onCollapse={(val) =>
setCollapsedMap({
...collapsedMap(),
[`group-${proxy.name}`]: val,
})
}
></Collapse>
)
}}
</For>
</div>
</div>
Expand All @@ -103,30 +88,28 @@ export default () => {

<div class="grid grid-cols-1 gap-2 sm:grid-cols-1">
<For each={proxyProviders()}>
{(proxy) => (
<div
class={twMerge(
getCollapseClassName(proxy.name),
'collapse-arrow collapse border-secondary bg-base-200 p-4',
)}
>
<div
class="collapse-title text-xl font-medium"
onClick={() => onCollapseTitleClick(proxy.name)}
>
{proxy.name}
</div>
<div class="collapse-content grid grid-cols-1 gap-2 sm:grid-cols-3 lg:grid-cols-5">
<For each={proxy.proxies}>
{(proxyNode) => (
<div class="card card-bordered card-compact m-1 flex-row justify-between border-secondary p-4">
{proxyNode.name} {renderDelay(proxyNode.name)}
</div>
)}
</For>
</div>
</div>
)}
{(proxyProvider) => {
const title = <>{proxyProvider.name}</>
const content = (
<For each={proxyProvider.proxies}>
{(proxy) => <ProxyNodeCard proxyName={proxy.name} />}
</For>
)

return (
<Collapse
isOpen={collapsedMap()[`provider-${proxyProvider.name}`]}
title={title}
content={content}
onCollapse={(val) =>
setCollapsedMap({
...collapsedMap(),
[`provider-${proxyProvider.name}`]: val,
})
}
/>
)
}}
</For>
</div>
</div>
Expand Down
8 changes: 5 additions & 3 deletions src/signals/proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { createSignal } from 'solid-js'
import { useRequest } from '~/signals'
import type { Proxy, ProxyProvider } from '~/types'

// these signals should be global state
const [proxies, setProxies] = createSignal<Proxy[]>([])
const [delayMap, setDelayMap] = createSignal<Record<string, number>>({})
const [proxyProviders, setProxyProviders] = createSignal<ProxyProvider[]>([])

export function useProxies() {
const request = useRequest()
const [proxies, setProxies] = createSignal<Proxy[]>([])
const [proxyProviders, setProxyProviders] = createSignal<ProxyProvider[]>([])
const [delayMap, setDelayMap] = createSignal<Record<string, number>>({})

const updateProxy = async () => {
const { providers } = await request
Expand Down