Skip to content

Commit

Permalink
feat: webui检查更新&修复日志字体渲染
Browse files Browse the repository at this point in the history
  • Loading branch information
bietiaop committed Jan 26, 2025
1 parent 520cec0 commit 3917cb0
Show file tree
Hide file tree
Showing 9 changed files with 286 additions and 73 deletions.
5 changes: 3 additions & 2 deletions napcat.webui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
"preview": "vite preview"
},
"dependencies": {
"@monaco-editor/loader": "^1.4.0",
"@monaco-editor/react": "4.7.0-rc.0",
"@heroui/avatar": "2.2.7",
"@heroui/breadcrumbs": "2.2.7",
"@heroui/button": "2.2.10",
Expand All @@ -38,6 +36,8 @@
"@heroui/tabs": "2.2.8",
"@heroui/theme": "2.4.6",
"@heroui/tooltip": "2.2.8",
"@monaco-editor/loader": "^1.4.0",
"@monaco-editor/react": "4.7.0-rc.0",
"@react-aria/visually-hidden": "3.8.18",
"@reduxjs/toolkit": "^2.5.0",
"@uidotdev/usehooks": "^2.4.1",
Expand All @@ -62,6 +62,7 @@
"react-hook-form": "^7.54.2",
"react-hot-toast": "^2.4.1",
"react-icons": "^5.4.0",
"react-markdown": "^9.0.3",
"react-redux": "^9.2.0",
"react-responsive": "^10.0.0",
"react-router-dom": "7.1.0",
Expand Down
2 changes: 0 additions & 2 deletions napcat.webui/src/components/log_com/realtime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ const RealTimeLogs = () => {
}
return logLevel.has(log.level)
})
.slice(-100)
.map((log) => colorizeLogLevelWithTag(log.message, log.level))
.join('\r\n')
Xterm.current?.clear()
Expand All @@ -65,7 +64,6 @@ const RealTimeLogs = () => {
useEffect(() => {
const subscribeLogs = () => {
try {
console.log('subscribeLogs')
const source = WebUIManager.getRealTimeLogs((data) => {
setDataArr((prev) => {
const newData = [...prev, ...data]
Expand Down
19 changes: 12 additions & 7 deletions napcat.webui/src/components/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,30 @@ export interface ModalProps {
content: React.ReactNode
title?: React.ReactNode
size?: React.ComponentProps<typeof NextUIModal>['size']
scrollBehavior?: React.ComponentProps<typeof NextUIModal>['scrollBehavior']
onClose?: () => void
onConfirm?: () => void
onCancel?: () => void
backdrop?: 'opaque' | 'blur' | 'transparent'
showCancel?: boolean
dismissible?: boolean
confirmText?: string
cancelText?: string
}

const Modal: React.FC<ModalProps> = React.memo((props) => {
const {
backdrop = 'blur',
title,
content,
size = 'md',
showCancel = true,
dismissible,
confirmText = '确定',
cancelText = '取消',
onClose,
onConfirm,
onCancel
onCancel,
...rest
} = props
const { onClose: onNativeClose } = useDisclosure()

Expand All @@ -44,19 +49,19 @@ const Modal: React.FC<ModalProps> = React.memo((props) => {
onClose?.()
onNativeClose()
}}
size={size}
classNames={{
backdrop: 'z-[99999999]',
wrapper: 'z-[999999999]'
}}
{...rest}
>
<ModalContent>
{(nativeClose) => (
<>
{title && (
<ModalHeader className="flex flex-col gap-1">{title}</ModalHeader>
)}
<ModalBody>{content}</ModalBody>
<ModalBody className="break-all">{content}</ModalBody>
<ModalFooter>
{showCancel && (
<Button
Expand All @@ -67,17 +72,17 @@ const Modal: React.FC<ModalProps> = React.memo((props) => {
nativeClose()
}}
>
取消
{cancelText}
</Button>
)}
<Button
color="primary"
color="danger"
onPress={() => {
onConfirm?.()
nativeClose()
}}
>
确定
{confirmText}
</Button>
</ModalFooter>
</>
Expand Down
171 changes: 151 additions & 20 deletions napcat.webui/src/components/system_info.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,188 @@
import { Button } from '@heroui/button'
import { Card, CardBody, CardHeader } from '@heroui/card'
import { Chip } from '@heroui/chip'
import { Spinner } from '@heroui/spinner'
import { Tooltip } from '@heroui/tooltip'
import { useRequest } from 'ahooks'
import { FaCircleInfo } from 'react-icons/fa6'
import { FaQq } from 'react-icons/fa6'
import { FaCircleInfo, FaInfo, FaQq } from 'react-icons/fa6'
import { IoLogoChrome, IoLogoOctocat } from 'react-icons/io'
import { RiMacFill } from 'react-icons/ri'

import useDialog from '@/hooks/use-dialog'

import { request } from '@/utils/request'
import { compareVersion } from '@/utils/version'

import WebUIManager from '@/controllers/webui_manager'
import { GithubRelease } from '@/types/github'

import packageJson from '../../package.json'
import TailwindMarkdown from './tailwind_markdown'

export interface SystemInfoItemProps {
title: string
icon?: React.ReactNode
value?: React.ReactNode
endContent?: React.ReactNode
}

const SystemInfoItem: React.FC<SystemInfoItemProps> = ({
title,
value = '--',
icon
icon,
endContent
}) => {
return (
<div className="flex text-sm gap-1 p-2 items-center shadow-sm shadow-danger-50 dark:shadow-danger-100 rounded text-danger-400">
{icon}
<div className="w-24">{title}</div>
<div className="text-danger-200">{value}</div>
<div className="ml-auto">{endContent}</div>
</div>
)
}

export interface SystemInfoProps {
archInfo?: string
export interface NewVersionTipProps {
currentVersion?: string
}
const SystemInfo: React.FC<SystemInfoProps> = (props) => {
const { archInfo } = props

const NewVersionTip = (props: NewVersionTipProps) => {
const { currentVersion } = props
const dialog = useDialog()
const { data: releaseData, error } = useRequest(() =>
request.get<GithubRelease[]>(
'https://api.github.com/repos/NapNeko/NapCatQQ/releases'
)
)

if (error) {
return (
<Tooltip content="检查新版本失败">
<Button
isIconOnly
radius="full"
color="danger"
variant="shadow"
className="!w-5 !h-5 !min-w-0 text-small shadow-md"
onPress={() => {
dialog.alert({
title: '检查新版本失败',
content: error.message
})
}}
>
<FaInfo />
</Button>
</Tooltip>
)
}

const latestVersion = releaseData?.data?.[0]?.tag_name

if (!latestVersion || !currentVersion) {
return null
}

if (compareVersion(latestVersion, currentVersion) <= 0) {
return null
}

const middleVersions: GithubRelease[] = []

for (let i = 0; i < releaseData.data.length; i++) {
const versionInfo = releaseData.data[i]
if (compareVersion(versionInfo.tag_name, currentVersion) > 0) {
middleVersions.push(versionInfo)
} else {
break
}
}

return (
<Tooltip content="有新版本可用">
<Button
isIconOnly
radius="full"
color="danger"
variant="shadow"
className="!w-5 !h-5 !min-w-0 text-small shadow-md"
onPress={() => {
dialog.confirm({
title: '有新版本可用',
content: (
<div className="space-y-2">
<div className="text-sm space-x-2">
<span>当前版本</span>
<Chip color="primary" variant="flat">
v{currentVersion}
</Chip>
</div>
<div className="text-sm space-x-2">
<span>最新版本</span>
<Chip color="primary">{latestVersion}</Chip>
</div>
<div className="text-sm space-y-2 !mt-4">
{middleVersions.map((versionInfo) => (
<div
key={versionInfo.tag_name}
className="p-4 bg-content1 rounded-md shadow-small"
>
<TailwindMarkdown content={versionInfo.body} />
</div>
))}
</div>
</div>
),
scrollBehavior: 'inside',
size: '3xl',
confirmText: '前往下载',
onConfirm() {
window.open(
'https://github.com/NapNeko/NapCatQQ/releases',
'_blank'
)
}
})
}}
>
<FaInfo />
</Button>
</Tooltip>
)
}

const NapCatVersion = () => {
const {
data: packageData,
loading: packageLoading,
error: packageError
} = useRequest(WebUIManager.getPackageInfo)

const currentVersion = packageData?.version

return (
<SystemInfoItem
title="NapCat 版本"
icon={<IoLogoOctocat className="text-xl" />}
value={
packageError ? (
`错误:${packageError.message}`
) : packageLoading ? (
<Spinner size="sm" />
) : (
currentVersion
)
}
endContent={<NewVersionTip currentVersion={currentVersion} />}
/>
)
}

export interface SystemInfoProps {
archInfo?: string
}
const SystemInfo: React.FC<SystemInfoProps> = (props) => {
const { archInfo } = props
const {
data: qqVersionData,
loading: qqVersionLoading,
Expand All @@ -53,19 +196,7 @@ const SystemInfo: React.FC<SystemInfoProps> = (props) => {
</CardHeader>
<CardBody className="flex-1">
<div className="flex flex-col justify-between h-full">
<SystemInfoItem
title="NapCat 版本"
icon={<IoLogoOctocat className="text-xl" />}
value={
packageError ? (
`错误:${packageError.message}`
) : packageLoading ? (
<Spinner size="sm" />
) : (
packageData?.version
)
}
/>
<NapCatVersion />
<SystemInfoItem
title="WebUI 版本"
icon={<IoLogoChrome className="text-xl" />}
Expand Down
49 changes: 49 additions & 0 deletions napcat.webui/src/components/tailwind_markdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Markdown from 'react-markdown'
import remarkGfm from 'remark-gfm'

const TailwindMarkdown: React.FC<{ content: string }> = ({ content }) => {
return (
<Markdown
className="prose prose-sm sm:prose lg:prose-lg xl:prose-xl"
remarkPlugins={[remarkGfm]}
components={{
h1: ({ node, ...props }) => (
<h1 className="text-2xl font-bold" {...props} />
),
h2: ({ node, ...props }) => (
<h2 className="text-xl font-bold" {...props} />
),
h3: ({ node, ...props }) => (
<h3 className="text-lg font-bold" {...props} />
),
p: ({ node, ...props }) => <p className="m-0" {...props} />,
a: ({ node, ...props }) => (
<a
className="text-blue-500 hover:underline"
target="_blank"
{...props}
/>
),
ul: ({ node, ...props }) => (
<ul className="list-disc list-inside" {...props} />
),
ol: ({ node, ...props }) => (
<ol className="list-decimal list-inside" {...props} />
),
blockquote: ({ node, ...props }) => (
<blockquote
className="border-l-4 border-gray-300 pl-4 italic"
{...props}
/>
),
code: ({ node, ...props }) => (
<code className="bg-gray-100 p-1 rounded" {...props} />
)
}}
>
{content}
</Markdown>
)
}

export default TailwindMarkdown
Loading

0 comments on commit 3917cb0

Please sign in to comment.