mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-22 00:13:09 +08:00
refactor: remove unused files and configurations (#11176)
* ♻️ refactor: remove unused resources/js directory and references
Remove legacy resources/js directory (bridge.js and utils.js) that was left over after minapp.html removal in commit 461458e5e. Also update .oxlintrc.json to remove the unused resources/js/** file pattern.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* ♻️ refactor: remove additional unused files
- Remove duplicate ipService.js (superseded by TypeScript version in src/main/utils/)
- Remove unused components.json (shadcn config with non-existent target directory)
- Remove unused context-menu.tsx component (no imports found)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
120ac122eb
commit
e43562423e
@ -35,8 +35,7 @@
|
|||||||
"files": [
|
"files": [
|
||||||
"src/renderer/**/*.{ts,tsx}",
|
"src/renderer/**/*.{ts,tsx}",
|
||||||
"packages/aiCore/**",
|
"packages/aiCore/**",
|
||||||
"packages/extension-table-plus/**",
|
"packages/extension-table-plus/**"
|
||||||
"resources/js/**"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://ui.shadcn.com/schema.json",
|
|
||||||
"aliases": {
|
|
||||||
"components": "@renderer/ui/third-party",
|
|
||||||
"hooks": "@renderer/hooks",
|
|
||||||
"lib": "@renderer/lib",
|
|
||||||
"ui": "@renderer/ui",
|
|
||||||
"utils": "@renderer/utils"
|
|
||||||
},
|
|
||||||
"iconLibrary": "lucide",
|
|
||||||
"rsc": false,
|
|
||||||
"style": "new-york",
|
|
||||||
"tailwind": {
|
|
||||||
"baseColor": "zinc",
|
|
||||||
"config": "",
|
|
||||||
"css": "src/renderer/src/assets/styles/tailwind.css",
|
|
||||||
"cssVariables": true,
|
|
||||||
"prefix": ""
|
|
||||||
},
|
|
||||||
"tsx": true
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
;(() => {
|
|
||||||
let messageId = 0
|
|
||||||
const pendingCalls = new Map()
|
|
||||||
|
|
||||||
function api(method, ...args) {
|
|
||||||
const id = messageId++
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
pendingCalls.set(id, { resolve, reject })
|
|
||||||
window.parent.postMessage({ id, type: 'api-call', method, args }, '*')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('message', (event) => {
|
|
||||||
if (event.data.type === 'api-response') {
|
|
||||||
const { id, result, error } = event.data
|
|
||||||
const pendingCall = pendingCalls.get(id)
|
|
||||||
if (pendingCall) {
|
|
||||||
if (error) {
|
|
||||||
pendingCall.reject(new Error(error))
|
|
||||||
} else {
|
|
||||||
pendingCall.resolve(result)
|
|
||||||
}
|
|
||||||
pendingCalls.delete(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
window.api = new Proxy(
|
|
||||||
{},
|
|
||||||
{
|
|
||||||
get: (target, prop) => {
|
|
||||||
return (...args) => api(prop, ...args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})()
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
export function getQueryParam(paramName) {
|
|
||||||
const url = new URL(window.location.href)
|
|
||||||
const params = new URLSearchParams(url.search)
|
|
||||||
return params.get(paramName)
|
|
||||||
}
|
|
||||||
@ -1,88 +0,0 @@
|
|||||||
const https = require('https')
|
|
||||||
const { loggerService } = require('@logger')
|
|
||||||
|
|
||||||
const logger = loggerService.withContext('IpService')
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取用户的IP地址所在国家
|
|
||||||
* @returns {Promise<string>} 返回国家代码,默认为'CN'
|
|
||||||
*/
|
|
||||||
async function getIpCountry() {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
// 添加超时控制
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
logger.info('IP Address Check Timeout, default to China Mirror')
|
|
||||||
resolve('CN')
|
|
||||||
}, 5000)
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
hostname: 'ipinfo.io',
|
|
||||||
path: '/json',
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'User-Agent':
|
|
||||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
|
|
||||||
'Accept-Language': 'en-US,en;q=0.9'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const req = https.request(options, (res) => {
|
|
||||||
clearTimeout(timeout)
|
|
||||||
let data = ''
|
|
||||||
|
|
||||||
res.on('data', (chunk) => {
|
|
||||||
data += chunk
|
|
||||||
})
|
|
||||||
|
|
||||||
res.on('end', () => {
|
|
||||||
try {
|
|
||||||
const parsed = JSON.parse(data)
|
|
||||||
const country = parsed.country || 'CN'
|
|
||||||
logger.info(`Detected user IP address country: ${country}`)
|
|
||||||
resolve(country)
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Failed to parse IP address information:', error.message)
|
|
||||||
resolve('CN')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
req.on('error', (error) => {
|
|
||||||
clearTimeout(timeout)
|
|
||||||
logger.error('Failed to get IP address information:', error.message)
|
|
||||||
resolve('CN')
|
|
||||||
})
|
|
||||||
|
|
||||||
req.end()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查用户是否在中国
|
|
||||||
* @returns {Promise<boolean>} 如果用户在中国返回true,否则返回false
|
|
||||||
*/
|
|
||||||
async function isUserInChina() {
|
|
||||||
const country = await getIpCountry()
|
|
||||||
return country.toLowerCase() === 'cn'
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据用户位置获取适合的npm镜像URL
|
|
||||||
* @returns {Promise<string>} 返回npm镜像URL
|
|
||||||
*/
|
|
||||||
async function getNpmRegistryUrl() {
|
|
||||||
const inChina = await isUserInChina()
|
|
||||||
if (inChina) {
|
|
||||||
logger.info('User in China, using Taobao npm mirror')
|
|
||||||
return 'https://registry.npmmirror.com'
|
|
||||||
} else {
|
|
||||||
logger.info('User not in China, using default npm mirror')
|
|
||||||
return 'https://registry.npmjs.org'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getIpCountry,
|
|
||||||
isUserInChina,
|
|
||||||
getNpmRegistryUrl
|
|
||||||
}
|
|
||||||
@ -1,207 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import * as React from 'react'
|
|
||||||
import * as ContextMenuPrimitive from '@radix-ui/react-context-menu'
|
|
||||||
import { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react'
|
|
||||||
import { cn } from '@renderer/utils'
|
|
||||||
|
|
||||||
function ContextMenu({ ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {
|
|
||||||
return <ContextMenuPrimitive.Root data-slot="context-menu" {...props} />
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContextMenuTrigger({ ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) {
|
|
||||||
return <ContextMenuPrimitive.Trigger data-slot="context-menu-trigger" {...props} />
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContextMenuGroup({ ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {
|
|
||||||
return <ContextMenuPrimitive.Group data-slot="context-menu-group" {...props} />
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContextMenuPortal({ ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Portal>) {
|
|
||||||
return <ContextMenuPrimitive.Portal data-slot="context-menu-portal" {...props} />
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContextMenuSub({ ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {
|
|
||||||
return <ContextMenuPrimitive.Sub data-slot="context-menu-sub" {...props} />
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContextMenuRadioGroup({ ...props }: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>) {
|
|
||||||
return <ContextMenuPrimitive.RadioGroup data-slot="context-menu-radio-group" {...props} />
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContextMenuSubTrigger({
|
|
||||||
className,
|
|
||||||
inset,
|
|
||||||
children,
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & {
|
|
||||||
inset?: boolean
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<ContextMenuPrimitive.SubTrigger
|
|
||||||
data-slot="context-menu-sub-trigger"
|
|
||||||
data-inset={inset}
|
|
||||||
className={cn(
|
|
||||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[inset]:pl-8 data-[state=open]:text-accent-foreground [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}>
|
|
||||||
{children}
|
|
||||||
<ChevronRightIcon className="ml-auto" />
|
|
||||||
</ContextMenuPrimitive.SubTrigger>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContextMenuSubContent({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>) {
|
|
||||||
return (
|
|
||||||
<ContextMenuPrimitive.SubContent
|
|
||||||
data-slot="context-menu-sub-content"
|
|
||||||
className={cn(
|
|
||||||
'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 z-50 min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=closed]:animate-out data-[state=open]:animate-in',
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContextMenuContent({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Content>) {
|
|
||||||
return (
|
|
||||||
<ContextMenuPrimitive.Portal>
|
|
||||||
<ContextMenuPrimitive.Content
|
|
||||||
data-slot="context-menu-content"
|
|
||||||
className={cn(
|
|
||||||
'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 z-50 max-h-(--radix-context-menu-content-available-height) min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=closed]:animate-out data-[state=open]:animate-in',
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
</ContextMenuPrimitive.Portal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContextMenuItem({
|
|
||||||
className,
|
|
||||||
inset,
|
|
||||||
variant = 'default',
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
|
|
||||||
inset?: boolean
|
|
||||||
variant?: 'default' | 'destructive'
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<ContextMenuPrimitive.Item
|
|
||||||
data-slot="context-menu-item"
|
|
||||||
data-inset={inset}
|
|
||||||
data-variant={variant}
|
|
||||||
className={cn(
|
|
||||||
"data-[variant=destructive]:*:[svg]:!text-destructive relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[disabled]:opacity-50 data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContextMenuCheckboxItem({
|
|
||||||
className,
|
|
||||||
children,
|
|
||||||
checked,
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>) {
|
|
||||||
return (
|
|
||||||
<ContextMenuPrimitive.CheckboxItem
|
|
||||||
data-slot="context-menu-checkbox-item"
|
|
||||||
className={cn(
|
|
||||||
"relative flex cursor-default select-none items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
checked={checked}
|
|
||||||
{...props}>
|
|
||||||
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
|
||||||
<ContextMenuPrimitive.ItemIndicator>
|
|
||||||
<CheckIcon className="size-4" />
|
|
||||||
</ContextMenuPrimitive.ItemIndicator>
|
|
||||||
</span>
|
|
||||||
{children}
|
|
||||||
</ContextMenuPrimitive.CheckboxItem>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContextMenuRadioItem({
|
|
||||||
className,
|
|
||||||
children,
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>) {
|
|
||||||
return (
|
|
||||||
<ContextMenuPrimitive.RadioItem
|
|
||||||
data-slot="context-menu-radio-item"
|
|
||||||
className={cn(
|
|
||||||
"relative flex cursor-default select-none items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}>
|
|
||||||
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
|
||||||
<ContextMenuPrimitive.ItemIndicator>
|
|
||||||
<CircleIcon className="size-2 fill-current" />
|
|
||||||
</ContextMenuPrimitive.ItemIndicator>
|
|
||||||
</span>
|
|
||||||
{children}
|
|
||||||
</ContextMenuPrimitive.RadioItem>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContextMenuLabel({
|
|
||||||
className,
|
|
||||||
inset,
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof ContextMenuPrimitive.Label> & {
|
|
||||||
inset?: boolean
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<ContextMenuPrimitive.Label
|
|
||||||
data-slot="context-menu-label"
|
|
||||||
data-inset={inset}
|
|
||||||
className={cn('px-2 py-1.5 font-medium text-foreground text-sm data-[inset]:pl-8', className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContextMenuSeparator({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Separator>) {
|
|
||||||
return (
|
|
||||||
<ContextMenuPrimitive.Separator
|
|
||||||
data-slot="context-menu-separator"
|
|
||||||
className={cn('-mx-1 my-1 h-px bg-border', className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ContextMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
data-slot="context-menu-shortcut"
|
|
||||||
className={cn('ml-auto text-muted-foreground text-xs tracking-widest', className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
ContextMenu,
|
|
||||||
ContextMenuTrigger,
|
|
||||||
ContextMenuContent,
|
|
||||||
ContextMenuItem,
|
|
||||||
ContextMenuCheckboxItem,
|
|
||||||
ContextMenuRadioItem,
|
|
||||||
ContextMenuLabel,
|
|
||||||
ContextMenuSeparator,
|
|
||||||
ContextMenuShortcut,
|
|
||||||
ContextMenuGroup,
|
|
||||||
ContextMenuPortal,
|
|
||||||
ContextMenuSub,
|
|
||||||
ContextMenuSubContent,
|
|
||||||
ContextMenuSubTrigger,
|
|
||||||
ContextMenuRadioGroup
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user