diff --git a/.github/workflows/auto-i18n.yml b/.github/workflows/auto-i18n.yml index 5797675347..4011698d79 100644 --- a/.github/workflows/auto-i18n.yml +++ b/.github/workflows/auto-i18n.yml @@ -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 diff --git a/package.json b/package.json index a651fe00de..64474b4b1f 100644 --- a/package.json +++ b/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" }, diff --git a/src/main/knowledge/langchain/loader/index.ts b/src/main/knowledge/langchain/loader/index.ts index f4718f71f8..dd89b5534c 100644 --- a/src/main/knowledge/langchain/loader/index.ts +++ b/src/main/knowledge/langchain/loader/index.ts @@ -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 diff --git a/src/renderer/src/pages/home/Messages/MessageVideo.tsx b/src/renderer/src/pages/home/Messages/MessageVideo.tsx index d0d9591372..979b50ab6e 100644 --- a/src/renderer/src/pages/home/Messages/MessageVideo.tsx +++ b/src/renderer/src/pages/home/Messages/MessageVideo.tsx @@ -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 = ({ block }) => { return null } - /** - * 渲染 YouTube 视频 - */ - const renderYoutube = () => { - if (!block.url) { - logger.warn('YouTube video was requested but block.url is missing.') - return
{t('message.video.error.youtube_url_missing')}
- } - - 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 - } - /** * 渲染本地视频文件 */ @@ -79,9 +54,6 @@ const MessageVideo: FC = ({ block }) => { const renderVideo = () => { switch (block.metadata?.type) { - case 'youtube': - return renderYoutube() - case 'video': return renderLocalVideo() diff --git a/src/renderer/src/pages/knowledge/components/KnowledgeSearchItem/VideoItem.tsx b/src/renderer/src/pages/knowledge/components/KnowledgeSearchItem/VideoItem.tsx index 0c33d148be..daef3d638a 100644 --- a/src/renderer/src/pages/knowledge/components/KnowledgeSearchItem/VideoItem.tsx +++ b/src/renderer/src/pages/knowledge/components/KnowledgeSearchItem/VideoItem.tsx @@ -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 = ({ item, searchKeyword }) => { const { highlightText } = useHighlightText() - /** - * 渲染 YouTube 视频 - */ - const renderYoutube = () => { - if (!item.metadata.source) { - logger.warn('YouTube video was requested but block.url is missing.') - return {t('knowledge.error.video.youtube_url_missing')} - } - - 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 ( - - ) - } - /** * 渲染本地视频文件 */ @@ -93,9 +61,6 @@ const VideoItem: FC = ({ item, searchKeyword }) => { const renderVideo = () => { switch (item.metadata?.type) { - case 'youtube': - return renderYoutube() - case 'video': return renderLocalVideo() diff --git a/src/renderer/src/pages/translate/TranslatePage.tsx b/src/renderer/src/pages/translate/TranslatePage.tsx index 1c9bd94839..66fcb0d9a4 100644 --- a/src/renderer/src/pages/translate/TranslatePage.tsx +++ b/src/renderer/src/pages/translate/TranslatePage.tsx @@ -612,9 +612,14 @@ const TranslatePage: FC = () => { // 粘贴上传文件 const onPaste = useCallback( async (event: React.ClipboardEvent) => { + 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 (