mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-26 20:50:30 +08:00
parent
14075c6b9b
commit
b1e39ab4b3
@ -167,86 +167,85 @@ const OverrideItem: React.FC<Props> = (props) => {
|
|||||||
setOpenFileEditor(true)
|
setOpenFileEditor(true)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CardBody>
|
<div ref={setNodeRef} {...attributes} {...listeners} className="h-full w-full">
|
||||||
<div className="flex justify-between h-[32px]">
|
<CardBody>
|
||||||
<h3
|
<div className="flex justify-between h-[32px]">
|
||||||
ref={setNodeRef}
|
<h3
|
||||||
{...attributes}
|
title={info?.name}
|
||||||
{...listeners}
|
className={`text-ellipsis whitespace-nowrap overflow-hidden text-md font-bold leading-[32px] text-foreground`}
|
||||||
title={info?.name}
|
>
|
||||||
className={`text-ellipsis whitespace-nowrap overflow-hidden text-md font-bold leading-[32px] text-foreground`}
|
{info?.name}
|
||||||
>
|
</h3>
|
||||||
{info?.name}
|
<div className="flex">
|
||||||
</h3>
|
{info.type === 'remote' && (
|
||||||
<div className="flex">
|
<Button
|
||||||
{info.type === 'remote' && (
|
isIconOnly
|
||||||
<Button
|
size="sm"
|
||||||
isIconOnly
|
variant="light"
|
||||||
size="sm"
|
|
||||||
variant="light"
|
|
||||||
color="default"
|
|
||||||
disabled={updating}
|
|
||||||
onPress={async () => {
|
|
||||||
setUpdating(true)
|
|
||||||
try {
|
|
||||||
await addOverrideItem(info)
|
|
||||||
await restartCore()
|
|
||||||
} catch (e) {
|
|
||||||
alert(e)
|
|
||||||
} finally {
|
|
||||||
setUpdating(false)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IoMdRefresh
|
|
||||||
color="default"
|
color="default"
|
||||||
className={`text-[24px] ${updating ? 'animate-spin' : ''}`}
|
disabled={updating}
|
||||||
/>
|
onPress={async () => {
|
||||||
</Button>
|
setUpdating(true)
|
||||||
)}
|
try {
|
||||||
|
await addOverrideItem(info)
|
||||||
<Dropdown>
|
await restartCore()
|
||||||
<DropdownTrigger>
|
} catch (e) {
|
||||||
<Button isIconOnly size="sm" variant="light" color="default">
|
alert(e)
|
||||||
<IoMdMore color="default" className={`text-[24px]`} />
|
} finally {
|
||||||
|
setUpdating(false)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IoMdRefresh
|
||||||
|
color="default"
|
||||||
|
className={`text-[24px] ${updating ? 'animate-spin' : ''}`}
|
||||||
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownTrigger>
|
)}
|
||||||
<DropdownMenu onAction={onMenuAction}>
|
|
||||||
{menuItems.map((item) => (
|
<Dropdown>
|
||||||
<DropdownItem
|
<DropdownTrigger>
|
||||||
showDivider={item.showDivider}
|
<Button isIconOnly size="sm" variant="light" color="default">
|
||||||
key={item.key}
|
<IoMdMore color="default" className={`text-[24px]`} />
|
||||||
color={item.color}
|
</Button>
|
||||||
className={item.className}
|
</DropdownTrigger>
|
||||||
>
|
<DropdownMenu onAction={onMenuAction}>
|
||||||
{item.label}
|
{menuItems.map((item) => (
|
||||||
</DropdownItem>
|
<DropdownItem
|
||||||
))}
|
showDivider={item.showDivider}
|
||||||
</DropdownMenu>
|
key={item.key}
|
||||||
</Dropdown>
|
color={item.color}
|
||||||
</div>
|
className={item.className}
|
||||||
</div>
|
>
|
||||||
<div className="flex justify-between">
|
{item.label}
|
||||||
<div className={`mt-2 flex justify-start`}>
|
</DropdownItem>
|
||||||
{info.global && (
|
))}
|
||||||
<Chip size="sm" variant="dot" color="primary" className="mr-2">
|
</DropdownMenu>
|
||||||
全局
|
</Dropdown>
|
||||||
</Chip>
|
|
||||||
)}
|
|
||||||
<Chip size="sm" variant="bordered" className="mr-2">
|
|
||||||
{info.type === 'local' ? '本地' : '远程'}
|
|
||||||
</Chip>
|
|
||||||
<Chip size="sm" variant="bordered">
|
|
||||||
{info.ext === 'yaml' ? 'YAML' : 'JavaScript'}
|
|
||||||
</Chip>
|
|
||||||
</div>
|
|
||||||
{info.type === 'remote' && (
|
|
||||||
<div className={`mt-2 flex justify-end`}>
|
|
||||||
<small>{dayjs(info.updated).fromNow()}</small>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
</div>
|
||||||
</div>
|
<div className="flex justify-between">
|
||||||
</CardBody>
|
<div className={`mt-2 flex justify-start`}>
|
||||||
|
{info.global && (
|
||||||
|
<Chip size="sm" variant="dot" color="primary" className="mr-2">
|
||||||
|
全局
|
||||||
|
</Chip>
|
||||||
|
)}
|
||||||
|
<Chip size="sm" variant="bordered" className="mr-2">
|
||||||
|
{info.type === 'local' ? '本地' : '远程'}
|
||||||
|
</Chip>
|
||||||
|
<Chip size="sm" variant="bordered">
|
||||||
|
{info.ext === 'yaml' ? 'YAML' : 'JavaScript'}
|
||||||
|
</Chip>
|
||||||
|
</div>
|
||||||
|
{info.type === 'remote' && (
|
||||||
|
<div className={`mt-2 flex justify-end`}>
|
||||||
|
<small>{dayjs(info.updated).fromNow()}</small>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</CardBody>
|
||||||
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -174,7 +174,7 @@ const ProfileItem: React.FC<Props> = (props) => {
|
|||||||
<Card
|
<Card
|
||||||
fullWidth
|
fullWidth
|
||||||
isPressable
|
isPressable
|
||||||
onClick={() => {
|
onPress={() => {
|
||||||
if (disableSelect) return
|
if (disableSelect) return
|
||||||
setSelecting(true)
|
setSelecting(true)
|
||||||
onClick().finally(() => {
|
onClick().finally(() => {
|
||||||
@ -183,129 +183,132 @@ const ProfileItem: React.FC<Props> = (props) => {
|
|||||||
}}
|
}}
|
||||||
className={`${isCurrent ? 'bg-primary' : ''} ${selecting ? 'blur-sm' : ''}`}
|
className={`${isCurrent ? 'bg-primary' : ''} ${selecting ? 'blur-sm' : ''}`}
|
||||||
>
|
>
|
||||||
<CardBody className="pb-1">
|
<div ref={setNodeRef} {...attributes} {...listeners} className="w-full h-full">
|
||||||
<div className="flex justify-between h-[32px]">
|
<CardBody className="pb-1">
|
||||||
<h3
|
<div className="flex justify-between h-[32px]">
|
||||||
ref={setNodeRef}
|
<h3
|
||||||
{...attributes}
|
title={info?.name}
|
||||||
{...listeners}
|
className={`text-ellipsis whitespace-nowrap overflow-hidden text-md font-bold leading-[32px] ${isCurrent ? 'text-primary-foreground' : 'text-foreground'}`}
|
||||||
title={info?.name}
|
>
|
||||||
className={`text-ellipsis whitespace-nowrap overflow-hidden text-md font-bold leading-[32px] ${isCurrent ? 'text-primary-foreground' : 'text-foreground'}`}
|
{info?.name}
|
||||||
>
|
</h3>
|
||||||
{info?.name}
|
<div className="flex">
|
||||||
</h3>
|
{info.type === 'remote' && (
|
||||||
<div className="flex">
|
<Tooltip placement="left" content={dayjs(info.updated).fromNow()}>
|
||||||
{info.type === 'remote' && (
|
<Button
|
||||||
<Tooltip placement="left" content={dayjs(info.updated).fromNow()}>
|
isIconOnly
|
||||||
|
size="sm"
|
||||||
|
variant="light"
|
||||||
|
color="default"
|
||||||
|
disabled={updating}
|
||||||
|
onPress={async () => {
|
||||||
|
setUpdating(true)
|
||||||
|
await addProfileItem(info)
|
||||||
|
setUpdating(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IoMdRefresh
|
||||||
|
color="default"
|
||||||
|
className={`${isCurrent ? 'text-primary-foreground' : 'text-foreground'} text-[24px] ${updating ? 'animate-spin' : ''}`}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Dropdown>
|
||||||
|
<DropdownTrigger>
|
||||||
|
<Button isIconOnly size="sm" variant="light" color="default">
|
||||||
|
<IoMdMore
|
||||||
|
color="default"
|
||||||
|
className={`text-[24px] ${isCurrent ? 'text-primary-foreground' : 'text-foreground'}`}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
</DropdownTrigger>
|
||||||
|
<DropdownMenu onAction={onMenuAction}>
|
||||||
|
{menuItems.map((item) => (
|
||||||
|
<DropdownItem
|
||||||
|
showDivider={item.showDivider}
|
||||||
|
key={item.key}
|
||||||
|
color={item.color}
|
||||||
|
className={item.className}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</DropdownItem>
|
||||||
|
))}
|
||||||
|
</DropdownMenu>
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{info.type === 'remote' && extra && (
|
||||||
|
<div
|
||||||
|
className={`mt-2 flex justify-between ${isCurrent ? 'text-primary-foreground' : 'text-foreground'}`}
|
||||||
|
>
|
||||||
|
<small>{`${calcTraffic(usage)}/${calcTraffic(total)}`}</small>
|
||||||
|
{profileDisplayDate === 'expire' ? (
|
||||||
<Button
|
<Button
|
||||||
isIconOnly
|
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="light"
|
variant="light"
|
||||||
color="default"
|
className="h-[20px] p-1 m-0"
|
||||||
disabled={updating}
|
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
setUpdating(true)
|
await patchAppConfig({ profileDisplayDate: 'update' })
|
||||||
await addProfileItem(info)
|
|
||||||
setUpdating(false)
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IoMdRefresh
|
{extra.expire ? dayjs.unix(extra.expire).format('YYYY-MM-DD') : '长期有效'}
|
||||||
color="default"
|
|
||||||
className={`${isCurrent ? 'text-primary-foreground' : 'text-foreground'} text-[24px] ${updating ? 'animate-spin' : ''}`}
|
|
||||||
/>
|
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
) : (
|
||||||
)}
|
<Button
|
||||||
|
size="sm"
|
||||||
<Dropdown>
|
variant="light"
|
||||||
<DropdownTrigger>
|
className="h-[20px] p-1 m-0"
|
||||||
<Button isIconOnly size="sm" variant="light" color="default">
|
onPress={async () => {
|
||||||
<IoMdMore
|
await patchAppConfig({ profileDisplayDate: 'expire' })
|
||||||
color="default"
|
}}
|
||||||
className={`text-[24px] ${isCurrent ? 'text-primary-foreground' : 'text-foreground'}`}
|
>
|
||||||
/>
|
{dayjs(info.updated).fromNow()}
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownTrigger>
|
)}
|
||||||
<DropdownMenu onAction={onMenuAction}>
|
</div>
|
||||||
{menuItems.map((item) => (
|
)}
|
||||||
<DropdownItem
|
</CardBody>
|
||||||
showDivider={item.showDivider}
|
<CardFooter className="pt-0">
|
||||||
key={item.key}
|
{info.type === 'remote' && !extra && (
|
||||||
color={item.color}
|
<div
|
||||||
className={item.className}
|
className={`w-full mt-2 flex justify-between ${isCurrent ? 'text-primary-foreground' : 'text-foreground'}`}
|
||||||
>
|
|
||||||
{item.label}
|
|
||||||
</DropdownItem>
|
|
||||||
))}
|
|
||||||
</DropdownMenu>
|
|
||||||
</Dropdown>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{info.type === 'remote' && extra && (
|
|
||||||
<div
|
|
||||||
className={`mt-2 flex justify-between ${isCurrent ? 'text-primary-foreground' : 'text-foreground'}`}
|
|
||||||
>
|
|
||||||
<small>{`${calcTraffic(usage)}/${calcTraffic(total)}`}</small>
|
|
||||||
{profileDisplayDate === 'expire' ? (
|
|
||||||
<small
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation()
|
|
||||||
patchAppConfig({ profileDisplayDate: 'update' })
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{extra.expire ? dayjs.unix(extra.expire).format('YYYY-MM-DD') : '长期有效'}
|
|
||||||
</small>
|
|
||||||
) : (
|
|
||||||
<small
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation()
|
|
||||||
patchAppConfig({ profileDisplayDate: 'expire' })
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{dayjs(info.updated).fromNow()}
|
|
||||||
</small>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</CardBody>
|
|
||||||
<CardFooter className="pt-0">
|
|
||||||
{info.type === 'remote' && !extra && (
|
|
||||||
<div
|
|
||||||
className={`w-full mt-2 flex justify-between ${isCurrent ? 'text-primary-foreground' : 'text-foreground'}`}
|
|
||||||
>
|
|
||||||
<Chip
|
|
||||||
size="sm"
|
|
||||||
variant="bordered"
|
|
||||||
className={`${isCurrent ? 'text-primary-foreground border-primary-foreground' : 'border-primary text-primary'}`}
|
|
||||||
>
|
>
|
||||||
远程
|
<Chip
|
||||||
</Chip>
|
size="sm"
|
||||||
<small>{dayjs(info.updated).fromNow()}</small>
|
variant="bordered"
|
||||||
</div>
|
className={`${isCurrent ? 'text-primary-foreground border-primary-foreground' : 'border-primary text-primary'}`}
|
||||||
)}
|
>
|
||||||
{info.type === 'local' && (
|
远程
|
||||||
<div
|
</Chip>
|
||||||
className={`mt-2 flex justify-between ${isCurrent ? 'text-primary-foreground' : 'text-foreground'}`}
|
<small>{dayjs(info.updated).fromNow()}</small>
|
||||||
>
|
</div>
|
||||||
<Chip
|
)}
|
||||||
size="sm"
|
{info.type === 'local' && (
|
||||||
variant="bordered"
|
<div
|
||||||
className={`${isCurrent ? 'text-primary-foreground border-primary-foreground' : 'border-primary text-primary'}`}
|
className={`mt-2 flex justify-between ${isCurrent ? 'text-primary-foreground' : 'text-foreground'}`}
|
||||||
>
|
>
|
||||||
本地
|
<Chip
|
||||||
</Chip>
|
size="sm"
|
||||||
</div>
|
variant="bordered"
|
||||||
)}
|
className={`${isCurrent ? 'text-primary-foreground border-primary-foreground' : 'border-primary text-primary'}`}
|
||||||
{extra && (
|
>
|
||||||
<Progress
|
本地
|
||||||
className="w-full"
|
</Chip>
|
||||||
classNames={{
|
</div>
|
||||||
indicator: isCurrent ? 'bg-primary-foreground' : 'bg-foreground'
|
)}
|
||||||
}}
|
{extra && (
|
||||||
value={calcPercent(extra?.upload, extra?.download, extra?.total)}
|
<Progress
|
||||||
/>
|
className="w-full"
|
||||||
)}
|
classNames={{
|
||||||
</CardFooter>
|
indicator: isCurrent ? 'bg-primary-foreground' : 'bg-foreground'
|
||||||
|
}}
|
||||||
|
value={calcPercent(extra?.upload, extra?.download, extra?.total)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</CardFooter>
|
||||||
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -18,7 +18,7 @@ dayjs.extend(relativeTime)
|
|||||||
dayjs.locale('zh-cn')
|
dayjs.locale('zh-cn')
|
||||||
|
|
||||||
const ProfileCard: React.FC = () => {
|
const ProfileCard: React.FC = () => {
|
||||||
const { appConfig } = useAppConfig()
|
const { appConfig, patchAppConfig } = useAppConfig()
|
||||||
const { profileCardStatus = 'col-span-2', profileDisplayDate = 'expire' } = appConfig || {}
|
const { profileCardStatus = 'col-span-2', profileDisplayDate = 'expire' } = appConfig || {}
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const match = location.pathname.includes('/profiles')
|
const match = location.pathname.includes('/profiles')
|
||||||
@ -122,11 +122,27 @@ const ProfileCard: React.FC = () => {
|
|||||||
>
|
>
|
||||||
<small>{`${calcTraffic(usage)}/${calcTraffic(total)}`}</small>
|
<small>{`${calcTraffic(usage)}/${calcTraffic(total)}`}</small>
|
||||||
{profileDisplayDate === 'expire' ? (
|
{profileDisplayDate === 'expire' ? (
|
||||||
<small>
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="light"
|
||||||
|
className="h-[20px] p-1 m-0"
|
||||||
|
onPress={async () => {
|
||||||
|
await patchAppConfig({ profileDisplayDate: 'update' })
|
||||||
|
}}
|
||||||
|
>
|
||||||
{extra.expire ? dayjs.unix(extra.expire).format('YYYY-MM-DD') : '长期有效'}
|
{extra.expire ? dayjs.unix(extra.expire).format('YYYY-MM-DD') : '长期有效'}
|
||||||
</small>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<small>{dayjs(info.updated).fromNow()}</small>
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="light"
|
||||||
|
className="h-[20px] p-1 m-0"
|
||||||
|
onPress={async () => {
|
||||||
|
await patchAppConfig({ profileDisplayDate: 'expire' })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{dayjs(info.updated).fromNow()}
|
||||||
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user