refactor: more refactoring

This commit is contained in:
kunish 2023-09-03 03:36:12 +08:00
parent 461488c19f
commit 7f1805172a
No known key found for this signature in database
GPG Key ID: 647A12B4F782C430
5 changed files with 92 additions and 72 deletions

View File

@ -1,7 +1,7 @@
import { Navigate, Route, Routes, useNavigate } from '@solidjs/router' import { Navigate, Route, Routes, useNavigate } from '@solidjs/router'
import { Show, createEffect, lazy, onMount } from 'solid-js' import { Show, createEffect, lazy, onMount } from 'solid-js'
import { Header } from '~/components' import { Header } from '~/components'
import { ROUTE } from '~/constants' import { ROUTES } from '~/constants'
import { import {
curTheme, curTheme,
endpoint, endpoint,
@ -46,14 +46,14 @@ export const App = () => {
<div class="flex-1 overflow-y-auto overflow-x-hidden p-2 sm:p-4"> <div class="flex-1 overflow-y-auto overflow-x-hidden p-2 sm:p-4">
<Routes> <Routes>
<Show when={selectedEndpoint()}> <Show when={selectedEndpoint()}>
<Route path={ROUTE.Overview} component={Overview} /> <Route path={ROUTES.Overview} component={Overview} />
<Route path={ROUTE.Proxies} component={Proxies} /> <Route path={ROUTES.Proxies} component={Proxies} />
<Route path={ROUTE.Proxyprovider} component={ProxyProvider} /> <Route path={ROUTES.Proxyprovider} component={ProxyProvider} />
<Route path={ROUTE.Rules} component={Rules} /> <Route path={ROUTES.Rules} component={Rules} />
<Route path={ROUTE.Conns} component={Connections} /> <Route path={ROUTES.Conns} component={Connections} />
<Route path={ROUTE.Log} component={Logs} /> <Route path={ROUTES.Log} component={Logs} />
<Route path={ROUTE.Config} component={Config} /> <Route path={ROUTES.Config} component={Config} />
<Route path="*" element={<Navigate href={ROUTE.Overview} />} /> <Route path="*" element={<Navigate href={ROUTES.Overview} />} />
</Show> </Show>
<Route path="/setup" component={Setup} /> <Route path="/setup" component={Setup} />

View File

@ -13,23 +13,29 @@ import {
createSortable, createSortable,
useDragDropContext, useDragDropContext,
} from '@thisbeyond/solid-dnd' } from '@thisbeyond/solid-dnd'
import { For, Show, createSignal } from 'solid-js' import { Component, For, Show, createSignal } from 'solid-js'
import { Button } from '~/components' import { Button } from '~/components'
import { AccessorKey, initColumnOrder, initColumnVisibility } from '~/constants' import {
CONNECTIONS_TABLE_ACCESSOR_KEY,
CONNECTIONS_TABLE_INITIAL_COLUMN_ORDER,
CONNECTIONS_TABLE_INITIAL_COLUMN_VISIBILITY,
} from '~/constants'
type ColumnVisibility = Partial<Record<AccessorKey, boolean>> type ColumnVisibility = Partial<Record<CONNECTIONS_TABLE_ACCESSOR_KEY, boolean>>
type ColumnOrder = AccessorKey[] type ColumnOrder = CONNECTIONS_TABLE_ACCESSOR_KEY[]
export const ConnectionsModal = (props: { export const ConnectionsTableOrderingModal = (props: {
order: ColumnOrder order: ColumnOrder
visible: ColumnVisibility visible: ColumnVisibility
onOrderChange: (value: ColumnOrder) => void onOrderChange: (value: ColumnOrder) => void
onVisibleChange: (value: ColumnVisibility) => void onVisibleChange: (value: ColumnVisibility) => void
}) => { }) => {
const [t] = useI18n() const [t] = useI18n()
const [activeKey, setActiveKey] = createSignal<AccessorKey | null>(null) const [activeKey, setActiveKey] =
createSignal<CONNECTIONS_TABLE_ACCESSOR_KEY | null>(null)
const onDragStart = ({ draggable }: { draggable: Draggable }) => const onDragStart = ({ draggable }: { draggable: Draggable }) =>
setActiveKey(draggable.id as AccessorKey) setActiveKey(draggable.id as CONNECTIONS_TABLE_ACCESSOR_KEY)
const onDragEnd = ({ const onDragEnd = ({
draggable, draggable,
droppable, droppable,
@ -39,8 +45,12 @@ export const ConnectionsModal = (props: {
}) => { }) => {
if (draggable && droppable) { if (draggable && droppable) {
const currentItems = props.order const currentItems = props.order
const fromIndex = currentItems.indexOf(draggable.id as AccessorKey) const fromIndex = currentItems.indexOf(
const toIndex = currentItems.indexOf(droppable.id as AccessorKey) draggable.id as CONNECTIONS_TABLE_ACCESSOR_KEY,
)
const toIndex = currentItems.indexOf(
droppable.id as CONNECTIONS_TABLE_ACCESSOR_KEY,
)
if (fromIndex !== toIndex) { if (fromIndex !== toIndex) {
const updatedItems = currentItems.slice() const updatedItems = currentItems.slice()
@ -51,8 +61,9 @@ export const ConnectionsModal = (props: {
} }
} }
const FormRow = (p: { key: AccessorKey }) => { const FormRow: Component<{
const key = p.key key: CONNECTIONS_TABLE_ACCESSOR_KEY
}> = ({ key }) => {
const sortable = createSortable(key) const sortable = createSortable(key)
const [state] = useDragDropContext()! const [state] = useDragDropContext()!
@ -109,8 +120,8 @@ export const ConnectionsModal = (props: {
<Button <Button
class="btn-neutral btn-sm ml-auto mt-4 block" class="btn-neutral btn-sm ml-auto mt-4 block"
onClick={() => { onClick={() => {
props.onOrderChange(initColumnOrder) props.onOrderChange(CONNECTIONS_TABLE_INITIAL_COLUMN_ORDER)
props.onVisibleChange(initColumnVisibility) props.onVisibleChange(CONNECTIONS_TABLE_INITIAL_COLUMN_VISIBILITY)
}} }}
> >
{t('reset')} {t('reset')}

View File

@ -16,7 +16,7 @@ import {
import { For, ParentComponent, Show, createMemo, createSignal } from 'solid-js' import { For, ParentComponent, Show, createMemo, createSignal } from 'solid-js'
import { twMerge } from 'tailwind-merge' import { twMerge } from 'tailwind-merge'
import { Button } from '~/components' import { Button } from '~/components'
import { LANG, ROUTE, themes } from '~/constants' import { LANG, ROUTES, themes } from '~/constants'
import { setCurTheme, setSelectedEndpoint, useProxies } from '~/signals' import { setCurTheme, setSelectedEndpoint, useProxies } from '~/signals'
const Nav: ParentComponent<{ href: string; tooltip: string }> = ({ const Nav: ParentComponent<{ href: string; tooltip: string }> = ({
@ -70,32 +70,32 @@ export const Header = () => {
const navs = createMemo(() => { const navs = createMemo(() => {
const list = [ const list = [
{ {
href: ROUTE.Overview, href: ROUTES.Overview,
name: t('overview'), name: t('overview'),
icon: <IconHome />, icon: <IconHome />,
}, },
{ {
href: ROUTE.Proxies, href: ROUTES.Proxies,
name: t('proxies'), name: t('proxies'),
icon: <IconGlobe />, icon: <IconGlobe />,
}, },
{ {
href: ROUTE.Rules, href: ROUTES.Rules,
name: t('rules'), name: t('rules'),
icon: <IconRuler />, icon: <IconRuler />,
}, },
{ {
href: ROUTE.Conns, href: ROUTES.Conns,
name: t('connections'), name: t('connections'),
icon: <IconNetwork />, icon: <IconNetwork />,
}, },
{ {
href: ROUTE.Log, href: ROUTES.Log,
name: t('logs'), name: t('logs'),
icon: <IconFileStack />, icon: <IconFileStack />,
}, },
{ {
href: ROUTE.Config, href: ROUTES.Config,
name: t('config'), name: t('config'),
icon: <IconSettings />, icon: <IconSettings />,
}, },
@ -103,7 +103,7 @@ export const Header = () => {
if (proxyProviders().length > 0) { if (proxyProviders().length > 0) {
list.splice(2, 0, { list.splice(2, 0, {
href: ROUTE.Proxyprovider, href: ROUTES.Proxyprovider,
name: t('proxyProviders'), name: t('proxyProviders'),
icon: <IconGlobeFilled />, icon: <IconGlobeFilled />,
}) })

View File

@ -30,7 +30,7 @@ export const themes = [
'winter', 'winter',
] ]
export enum ROUTE { export enum ROUTES {
Overview = '/overview', Overview = '/overview',
Proxies = '/proxies', Proxies = '/proxies',
Proxyprovider = '/proxyprovider', Proxyprovider = '/proxyprovider',
@ -40,22 +40,6 @@ export enum ROUTE {
Config = '/config', Config = '/config',
} }
export enum AccessorKey {
Close = 'close',
ID = 'ID',
Type = 'type',
Process = 'process',
Host = 'host',
Rule = 'rules',
Chains = 'chains',
DlSpeed = 'dlSpeed',
ULSpeed = 'ulSpeed',
Download = 'dl',
Upload = 'ul',
Source = 'source',
Destination = 'destination',
}
export enum DELAY { export enum DELAY {
NOT_CONNECTED = 0, NOT_CONNECTED = 0,
MEDIUM = 200, MEDIUM = 200,
@ -82,8 +66,28 @@ export enum LANG {
ZH = 'zh-CN', ZH = 'zh-CN',
} }
export const initColumnOrder = Object.values(AccessorKey) export enum CONNECTIONS_TABLE_ACCESSOR_KEY {
export const initColumnVisibility = { Close = 'close',
...Object.fromEntries(initColumnOrder.map((i) => [i, true])), ID = 'ID',
[AccessorKey.ID]: false, Type = 'type',
Process = 'process',
Host = 'host',
Rule = 'rules',
Chains = 'chains',
DlSpeed = 'dlSpeed',
ULSpeed = 'ulSpeed',
Download = 'dl',
Upload = 'ul',
Source = 'source',
Destination = 'destination',
}
export const CONNECTIONS_TABLE_INITIAL_COLUMN_ORDER = Object.values(
CONNECTIONS_TABLE_ACCESSOR_KEY,
)
export const CONNECTIONS_TABLE_INITIAL_COLUMN_VISIBILITY = {
...Object.fromEntries(
CONNECTIONS_TABLE_INITIAL_COLUMN_ORDER.map((i) => [i, true]),
),
[CONNECTIONS_TABLE_ACCESSOR_KEY.ID]: false,
} }

View File

@ -20,8 +20,12 @@ import byteSize from 'byte-size'
import { isIPv6 } from 'is-ip' import { isIPv6 } from 'is-ip'
import { For, createEffect, createSignal } from 'solid-js' import { For, createEffect, createSignal } from 'solid-js'
import { twMerge } from 'tailwind-merge' import { twMerge } from 'tailwind-merge'
import { Button, ConnectionsModal } from '~/components' import { Button, ConnectionsTableOrderingModal } from '~/components'
import { AccessorKey, initColumnOrder, initColumnVisibility } from '~/constants' import {
CONNECTIONS_TABLE_ACCESSOR_KEY,
CONNECTIONS_TABLE_INITIAL_COLUMN_ORDER,
CONNECTIONS_TABLE_INITIAL_COLUMN_VISIBILITY,
} from '~/constants'
import { secret, useRequest, wsEndpointURL } from '~/signals' import { secret, useRequest, wsEndpointURL } from '~/signals'
import type { Connection } from '~/types' import type { Connection } from '~/types'
@ -30,20 +34,20 @@ type ConnectionWithSpeed = Connection & {
uploadSpeed: number uploadSpeed: number
} }
type ColumnVisibility = Partial<Record<AccessorKey, boolean>> type ColumnVisibility = Partial<Record<CONNECTIONS_TABLE_ACCESSOR_KEY, boolean>>
type ColumnOrder = AccessorKey[] type ColumnOrder = CONNECTIONS_TABLE_ACCESSOR_KEY[]
export default () => { export default () => {
const [t] = useI18n() const [t] = useI18n()
const [columnVisibility, setColumnVisibility] = makePersisted( const [columnVisibility, setColumnVisibility] = makePersisted(
createSignal<ColumnVisibility>(initColumnVisibility), createSignal<ColumnVisibility>(CONNECTIONS_TABLE_INITIAL_COLUMN_VISIBILITY),
{ {
name: 'columnVisibility', name: 'columnVisibility',
storage: localStorage, storage: localStorage,
}, },
) )
const [columnOrder, setColumnOrder] = makePersisted( const [columnOrder, setColumnOrder] = makePersisted(
createSignal<ColumnOrder>(initColumnOrder), createSignal<ColumnOrder>(CONNECTIONS_TABLE_INITIAL_COLUMN_ORDER),
{ {
name: 'columnOrder', name: 'columnOrder',
storage: localStorage, storage: localStorage,
@ -104,7 +108,7 @@ export default () => {
const columns: ColumnDef<ConnectionWithSpeed>[] = [ const columns: ColumnDef<ConnectionWithSpeed>[] = [
{ {
accessorKey: AccessorKey.Close, accessorKey: CONNECTIONS_TABLE_ACCESSOR_KEY.Close,
header: () => ( header: () => (
<div class="flex h-full items-center"> <div class="flex h-full items-center">
<Button <Button
@ -127,68 +131,68 @@ export default () => {
), ),
}, },
{ {
accessorKey: AccessorKey.ID, accessorKey: CONNECTIONS_TABLE_ACCESSOR_KEY.ID,
accessorFn: (row) => row.id, accessorFn: (row) => row.id,
}, },
{ {
accessorKey: AccessorKey.Type, accessorKey: CONNECTIONS_TABLE_ACCESSOR_KEY.Type,
accessorFn: (row) => `${row.metadata.type}(${row.metadata.network})`, accessorFn: (row) => `${row.metadata.type}(${row.metadata.network})`,
}, },
{ {
accessorKey: AccessorKey.Process, accessorKey: CONNECTIONS_TABLE_ACCESSOR_KEY.Process,
accessorFn: (row) => accessorFn: (row) =>
row.metadata.process || row.metadata.process ||
row.metadata.processPath.replace(/^.*[/\\](.*)$/, '$1') || row.metadata.processPath.replace(/^.*[/\\](.*)$/, '$1') ||
'-', '-',
}, },
{ {
accessorKey: AccessorKey.Host, accessorKey: CONNECTIONS_TABLE_ACCESSOR_KEY.Host,
accessorFn: (row) => accessorFn: (row) =>
`${ `${
row.metadata.host ? row.metadata.host : row.metadata.destinationIP row.metadata.host ? row.metadata.host : row.metadata.destinationIP
}:${row.metadata.destinationPort}`, }:${row.metadata.destinationPort}`,
}, },
{ {
accessorKey: AccessorKey.Rule, accessorKey: CONNECTIONS_TABLE_ACCESSOR_KEY.Rule,
accessorFn: (row) => accessorFn: (row) =>
!row.rulePayload ? row.rule : `${row.rule} :: ${row.rulePayload}`, !row.rulePayload ? row.rule : `${row.rule} :: ${row.rulePayload}`,
}, },
{ {
accessorKey: AccessorKey.Chains, accessorKey: CONNECTIONS_TABLE_ACCESSOR_KEY.Chains,
accessorFn: (row) => row.chains.slice().reverse().join(' :: '), accessorFn: (row) => row.chains.slice().reverse().join(' :: '),
}, },
{ {
accessorKey: AccessorKey.DlSpeed, accessorKey: CONNECTIONS_TABLE_ACCESSOR_KEY.DlSpeed,
accessorFn: (row) => `${byteSize(row.downloadSpeed)}/s`, accessorFn: (row) => `${byteSize(row.downloadSpeed)}/s`,
sortingFn: (prev, next) => sortingFn: (prev, next) =>
prev.original.downloadSpeed - next.original.downloadSpeed, prev.original.downloadSpeed - next.original.downloadSpeed,
}, },
{ {
accessorKey: AccessorKey.ULSpeed, accessorKey: CONNECTIONS_TABLE_ACCESSOR_KEY.ULSpeed,
accessorFn: (row) => `${byteSize(row.uploadSpeed)}/s`, accessorFn: (row) => `${byteSize(row.uploadSpeed)}/s`,
sortingFn: (prev, next) => sortingFn: (prev, next) =>
prev.original.uploadSpeed - next.original.uploadSpeed, prev.original.uploadSpeed - next.original.uploadSpeed,
}, },
{ {
accessorKey: AccessorKey.Download, accessorKey: CONNECTIONS_TABLE_ACCESSOR_KEY.Download,
accessorFn: (row) => byteSize(row.download), accessorFn: (row) => byteSize(row.download),
sortingFn: (prev, next) => sortingFn: (prev, next) =>
prev.original.download - next.original.download, prev.original.download - next.original.download,
}, },
{ {
accessorKey: AccessorKey.Upload, accessorKey: CONNECTIONS_TABLE_ACCESSOR_KEY.Upload,
accessorFn: (row) => byteSize(row.upload), accessorFn: (row) => byteSize(row.upload),
sortingFn: (prev, next) => prev.original.upload - next.original.upload, sortingFn: (prev, next) => prev.original.upload - next.original.upload,
}, },
{ {
accessorKey: AccessorKey.Source, accessorKey: CONNECTIONS_TABLE_ACCESSOR_KEY.Source,
accessorFn: (row) => accessorFn: (row) =>
isIPv6(row.metadata.sourceIP) isIPv6(row.metadata.sourceIP)
? `[${row.metadata.sourceIP}]:${row.metadata.sourcePort}` ? `[${row.metadata.sourceIP}]:${row.metadata.sourcePort}`
: `${row.metadata.sourceIP}:${row.metadata.sourcePort}`, : `${row.metadata.sourceIP}:${row.metadata.sourcePort}`,
}, },
{ {
accessorKey: AccessorKey.Destination, accessorKey: CONNECTIONS_TABLE_ACCESSOR_KEY.Destination,
accessorFn: (row) => accessorFn: (row) =>
row.metadata.remoteDestination || row.metadata.remoteDestination ||
row.metadata.destinationIP || row.metadata.destinationIP ||
@ -243,7 +247,7 @@ export default () => {
<IconSettings /> <IconSettings />
</label> </label>
<ConnectionsModal <ConnectionsTableOrderingModal
order={columnOrder()} order={columnOrder()}
visible={columnVisibility()} visible={columnVisibility()}
onOrderChange={(data: ColumnOrder) => { onOrderChange={(data: ColumnOrder) => {
@ -272,7 +276,8 @@ export default () => {
)} )}
onClick={header.column.getToggleSortingHandler()} onClick={header.column.getToggleSortingHandler()}
> >
{header.column.id === AccessorKey.Close ? ( {header.column.id ===
CONNECTIONS_TABLE_ACCESSOR_KEY.Close ? (
flexRender( flexRender(
header.column.columnDef.header, header.column.columnDef.header,
header.getContext(), header.getContext(),