mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-31 08:29:07 +08:00
Merge branch 'CherryHQ:main' into main
This commit is contained in:
commit
039904c0a1
1
.github/workflows/auto-i18n.yml
vendored
1
.github/workflows/auto-i18n.yml
vendored
@ -13,6 +13,7 @@ on:
|
||||
jobs:
|
||||
auto-i18n:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.base.repo.full_name == 'CherryHQ/cherry-studio'
|
||||
name: Auto I18N
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
14
package.json
14
package.json
@ -74,23 +74,16 @@
|
||||
"@libsql/win32-x64-msvc": "^0.4.7",
|
||||
"@napi-rs/system-ocr": "patch:@napi-rs/system-ocr@npm%3A1.0.2#~/.yarn/patches/@napi-rs-system-ocr-npm-1.0.2-59e7a78e8b.patch",
|
||||
"@strongtz/win32-arm64-msvc": "^0.4.7",
|
||||
"cheerio": "^1.1.2",
|
||||
"faiss-node": "^0.5.1",
|
||||
"graceful-fs": "^4.2.11",
|
||||
"html-to-text": "^9.0.5",
|
||||
"htmlparser2": "^10.0.0",
|
||||
"jsdom": "26.1.0",
|
||||
"node-stream-zip": "^1.15.0",
|
||||
"officeparser": "^4.2.0",
|
||||
"os-proxy-config": "^1.1.2",
|
||||
"pdf-parse": "^1.1.1",
|
||||
"react-player": "^3.3.1",
|
||||
"react-youtube": "^10.1.0",
|
||||
"selection-hook": "^1.0.11",
|
||||
"sharp": "^0.34.3",
|
||||
"tesseract.js": "patch:tesseract.js@npm%3A6.0.1#~/.yarn/patches/tesseract.js-npm-6.0.1-2562a7e46d.patch",
|
||||
"turndown": "7.2.0",
|
||||
"youtubei.js": "^15.0.1"
|
||||
"turndown": "7.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@agentic/exa": "^7.3.3",
|
||||
@ -213,6 +206,7 @@
|
||||
"axios": "^1.7.3",
|
||||
"browser-image-compression": "^2.0.2",
|
||||
"chardet": "^2.1.0",
|
||||
"cheerio": "^1.1.2",
|
||||
"chokidar": "^4.0.3",
|
||||
"cli-progress": "^3.12.0",
|
||||
"code-inspector-plugin": "^0.20.14",
|
||||
@ -249,6 +243,7 @@
|
||||
"he": "^1.2.0",
|
||||
"html-tags": "^5.1.0",
|
||||
"html-to-image": "^1.11.13",
|
||||
"html-to-text": "^9.0.5",
|
||||
"htmlparser2": "^10.0.0",
|
||||
"husky": "^9.1.7",
|
||||
"i18next": "^23.11.5",
|
||||
@ -272,6 +267,7 @@
|
||||
"openai": "patch:openai@npm%3A5.12.2#~/.yarn/patches/openai-npm-5.12.2-30b075401c.patch",
|
||||
"p-queue": "^8.1.0",
|
||||
"pdf-lib": "^1.17.1",
|
||||
"pdf-parse": "^1.1.1",
|
||||
"playwright": "^1.52.0",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-sort-json": "^4.1.1",
|
||||
@ -284,6 +280,7 @@
|
||||
"react-infinite-scroll-component": "^6.1.0",
|
||||
"react-json-view": "^1.21.3",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-player": "^3.3.1",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-router": "6",
|
||||
"react-router-dom": "6",
|
||||
@ -326,6 +323,7 @@
|
||||
"word-extractor": "^1.0.4",
|
||||
"y-protocols": "^1.0.6",
|
||||
"yjs": "^13.6.27",
|
||||
"youtubei.js": "^15.0.1",
|
||||
"zipread": "^1.3.3",
|
||||
"zod": "^3.25.74"
|
||||
},
|
||||
|
||||
@ -153,8 +153,7 @@ export async function addWebLoader(
|
||||
case 'youtube':
|
||||
loaderInstance = YoutubeLoader.createFromUrl(url, {
|
||||
addVideoInfo: true,
|
||||
transcriptFormat: 'srt',
|
||||
language: 'zh'
|
||||
transcriptFormat: 'srt'
|
||||
})
|
||||
splitterType = 'srt'
|
||||
break
|
||||
|
||||
@ -3,7 +3,6 @@ import { VideoMessageBlock } from '@renderer/types/newMessage'
|
||||
import { FC, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import ReactPlayer from 'react-player'
|
||||
import YouTube, { YouTubeProps } from 'react-youtube'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const logger = loggerService.withContext('MessageVideo')
|
||||
@ -21,30 +20,6 @@ const MessageVideo: FC<Props> = ({ block }) => {
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染 YouTube 视频
|
||||
*/
|
||||
const renderYoutube = () => {
|
||||
if (!block.url) {
|
||||
logger.warn('YouTube video was requested but block.url is missing.')
|
||||
return <div>{t('message.video.error.youtube_url_missing')}</div>
|
||||
}
|
||||
|
||||
const onPlayerReady: YouTubeProps['onReady'] = (event) => {
|
||||
event.target.pauseVideo()
|
||||
}
|
||||
|
||||
const opts: YouTubeProps['opts'] = {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
playerVars: {
|
||||
start: Math.floor(block.metadata?.startTime ?? 0)
|
||||
}
|
||||
}
|
||||
|
||||
return <YouTube style={{ height: '100%', width: '100%' }} videoId={block.url} opts={opts} onReady={onPlayerReady} />
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染本地视频文件
|
||||
*/
|
||||
@ -79,9 +54,6 @@ const MessageVideo: FC<Props> = ({ block }) => {
|
||||
|
||||
const renderVideo = () => {
|
||||
switch (block.metadata?.type) {
|
||||
case 'youtube':
|
||||
return renderYoutube()
|
||||
|
||||
case 'video':
|
||||
return renderLocalVideo()
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@ import { FileMetadata, KnowledgeSearchResult } from '@renderer/types'
|
||||
import { Typography } from 'antd'
|
||||
import React, { FC, useRef } from 'react'
|
||||
import ReactPlayer from 'react-player'
|
||||
import YouTube, { YouTubeProps } from 'react-youtube'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const { Paragraph } = Typography
|
||||
@ -28,37 +27,6 @@ const VideoItem: FC<Props> = ({ item, searchKeyword }) => {
|
||||
|
||||
const { highlightText } = useHighlightText()
|
||||
|
||||
/**
|
||||
* 渲染 YouTube 视频
|
||||
*/
|
||||
const renderYoutube = () => {
|
||||
if (!item.metadata.source) {
|
||||
logger.warn('YouTube video was requested but block.url is missing.')
|
||||
return <ErrorContainer>{t('knowledge.error.video.youtube_url_missing')}</ErrorContainer>
|
||||
}
|
||||
|
||||
const onPlayerReady: YouTubeProps['onReady'] = (event) => {
|
||||
event.target.pauseVideo()
|
||||
}
|
||||
|
||||
const opts: YouTubeProps['opts'] = {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
playerVars: {
|
||||
start: Math.floor(item.metadata?.startTime ?? 0)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<YouTube
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
videoId={item.metadata.source}
|
||||
opts={opts}
|
||||
onReady={onPlayerReady}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染本地视频文件
|
||||
*/
|
||||
@ -93,9 +61,6 @@ const VideoItem: FC<Props> = ({ item, searchKeyword }) => {
|
||||
|
||||
const renderVideo = () => {
|
||||
switch (item.metadata?.type) {
|
||||
case 'youtube':
|
||||
return renderYoutube()
|
||||
|
||||
case 'video':
|
||||
return renderLocalVideo()
|
||||
|
||||
|
||||
@ -612,9 +612,14 @@ const TranslatePage: FC = () => {
|
||||
// 粘贴上传文件
|
||||
const onPaste = useCallback(
|
||||
async (event: React.ClipboardEvent<HTMLTextAreaElement>) => {
|
||||
event.preventDefault()
|
||||
if (isProcessing) return
|
||||
setIsProcessing(true)
|
||||
logger.debug('event', event)
|
||||
if (event.clipboardData?.files && event.clipboardData.files.length > 0) {
|
||||
const text = event.clipboardData.getData('text')
|
||||
if (!isEmpty(text)) {
|
||||
setText(text)
|
||||
} else if (event.clipboardData.files && event.clipboardData.files.length > 0) {
|
||||
event.preventDefault()
|
||||
const files = event.clipboardData.files
|
||||
const file = getSingleFile(files) as File
|
||||
@ -659,7 +664,7 @@ const TranslatePage: FC = () => {
|
||||
}
|
||||
setIsProcessing(false)
|
||||
},
|
||||
[getSingleFile, processFile, t]
|
||||
[getSingleFile, isProcessing, processFile, t]
|
||||
)
|
||||
return (
|
||||
<Container
|
||||
|
||||
@ -313,17 +313,6 @@ export function processKnowledgeReferences(
|
||||
}
|
||||
|
||||
switch (metadata.type) {
|
||||
case 'youtube': {
|
||||
onChunkReceived({
|
||||
type: ChunkType.VIDEO_SEARCHED,
|
||||
video: {
|
||||
type: 'url',
|
||||
content: metadata.source
|
||||
},
|
||||
metadata
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'video': {
|
||||
onChunkReceived({
|
||||
type: ChunkType.VIDEO_SEARCHED,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user