refactor: windows7 support

This commit is contained in:
kangfenmao 2025-05-07 10:14:27 +08:00
parent f844a7e024
commit 8fd57d0271
20 changed files with 534 additions and 431 deletions

View File

@ -38,24 +38,21 @@ files:
- '!node_modules/mammoth/{mammoth.browser.js,mammoth.browser.min.js}'
asarUnpack:
- resources/**
- '**/*.{metal,exp,lib}'
- '**/*.{node,dll,metal,exp,lib}'
win:
executableName: Cherry Studio
artifactName: ${productName}-${version}-${arch}-setup.${ext}
artifactName: ${productName}-${version}-portable.${ext}
target:
- target: nsis
- target: portable
nsis:
artifactName: ${productName}-${version}-${arch}-setup.${ext}
artifactName: ${productName}-${version}-setup.${ext}
shortcutName: ${productName}
uninstallDisplayName: ${productName}
createDesktopShortcut: always
allowToChangeInstallationDirectory: true
oneClick: false
include: build/nsis-installer.nsh
buildUniversalInstaller: false
portable:
artifactName: ${productName}-${version}-${arch}-portable.${ext}
mac:
entitlementsInherit: build/entitlements.mac.plist
notarize: false
@ -67,11 +64,20 @@ mac:
- NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder.
target:
- target: dmg
arch:
- arm64
- x64
- target: zip
arch:
- arm64
- x64
linux:
artifactName: ${productName}-${version}-${arch}.${ext}
target:
- target: AppImage
arch:
- arm64
- x64
maintainer: electronjs.org
category: Utility
desktop:
@ -80,13 +86,15 @@ linux:
mimeTypes:
- x-scheme-handler/cherrystudio
publish:
provider: generic
url: https://releases.cherry-ai.com
# provider: generic
# url: https://cherrystudio.ocool.online
provider: github
repo: cherry-studio
owner: CherryHQ
electronDownload:
mirror: https://npmmirror.com/mirrors/electron/
afterPack: scripts/after-pack.js
afterSign: scripts/notarize.js
artifactBuildCompleted: scripts/artifact-build-completed.js
releaseInfo:
releaseNotes: |
新增对 grok-2-image 和 gpt-4o-image 图像支持

View File

@ -1,5 +1,6 @@
import react from '@vitejs/plugin-react-swc'
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
import fs from 'fs'
import { resolve } from 'path'
import { visualizer } from 'rollup-plugin-visualizer'
@ -37,7 +38,27 @@ export default defineConfig({
},
build: {
rollupOptions: {
external: ['@libsql/client']
external: ['@libsql/client'],
plugins: [
{
name: 'inject-windows7-polyfill',
generateBundle(_, bundle) {
// 遍历所有生成的文件
for (const fileName in bundle) {
const chunk = bundle[fileName]
if (
chunk.type === 'chunk' &&
chunk.isEntry &&
chunk.fileName.includes('index.js') // 匹配主进程入口文件
) {
const code = fs.readFileSync('src/main/polyfill/windows7-patch.js', 'utf-8')
// 在文件末尾插入自定义代码
chunk.code = code + '\r\n' + chunk.code
}
}
}
}
]
}
}
},
@ -50,6 +71,10 @@ export default defineConfig({
}
},
renderer: {
define: {
// 使用方法 (Windows CMD): set CUSTOM_APP_NAME=AppName && yarn run dev
'process.env.CUSTOM_APP_NAME': JSON.stringify(process.env.CUSTOM_APP_NAME)
},
plugins: [
react({
plugins: [

View File

@ -26,6 +26,7 @@
"build:win": "dotenv npm run build && electron-builder --win --x64 --arm64",
"build:win:x64": "dotenv npm run build && electron-builder --win --x64",
"build:win:arm64": "dotenv npm run build && electron-builder --win --arm64",
"build:win7": "xcopy \"src\\patch\\windows7\\\" \"node_modules\\\" /E /Y && dotenv npm run build && electron-builder --win --x64",
"build:mac": "dotenv electron-vite build && electron-builder --mac --arm64 --x64",
"build:mac:arm64": "dotenv electron-vite build && electron-builder --mac --arm64",
"build:mac:x64": "dotenv electron-vite build && electron-builder --mac --x64",
@ -70,15 +71,19 @@
"@electron-toolkit/utils": "^3.0.0",
"@electron/notarize": "^2.5.0",
"@langchain/community": "^0.3.36",
"@libsql/client": "^0.15.2",
"@libsql/win32-x64-msvc": "^0.5.4",
"@strongtz/win32-arm64-msvc": "^0.4.7",
"@types/react-infinite-scroll-component": "^5.0.0",
"adm-zip": "^0.5.16",
"archiver": "^7.0.1",
"async-mutex": "^0.5.0",
"blob-polyfill": "^9.0.20240710",
"bufferutil": "^4.0.9",
"color": "^5.0.0",
"diff": "^7.0.0",
"docx": "^9.0.2",
"domexception": "^4.0.0",
"electron-log": "^5.1.5",
"electron-store": "^8.2.0",
"electron-updater": "patch:electron-updater@npm%3A6.6.3#~/.yarn/patches/electron-updater-npm-6.6.3-9269dbaf84.patch",
@ -90,7 +95,9 @@
"fs-extra": "^11.2.0",
"got-scraping": "^4.1.1",
"jsdom": "^26.0.0",
"libsql": "^0.5.4",
"markdown-it": "^14.1.0",
"node-fetch": "2",
"node-stream-zip": "^1.15.0",
"officeparser": "^4.1.1",
"os-proxy-config": "^1.1.2",
@ -99,6 +106,7 @@
"turndown": "^7.2.0",
"turndown-plugin-gfm": "^1.0.2",
"undici": "^7.4.0",
"web-streams-polyfill": "^4.1.0",
"webdav": "^5.8.0",
"ws": "^8.18.1",
"zipread": "^1.3.3"
@ -122,6 +130,7 @@
"@modelcontextprotocol/sdk": "^1.10.2",
"@mozilla/readability": "^0.6.0",
"@notionhq/client": "^2.2.15",
"@peculiar/webcrypto": "^1.5.0",
"@reduxjs/toolkit": "^2.2.5",
"@shikijs/markdown-it": "^3.2.2",
"@swc/plugin-styled-components": "^7.1.3",
@ -153,8 +162,8 @@
"dexie": "^4.0.8",
"dexie-react-hooks": "^1.1.7",
"dotenv-cli": "^7.4.2",
"electron": "31.7.6",
"electron-builder": "26.0.13",
"electron": "22.3.23",
"electron-builder": "^24.9.1",
"electron-devtools-installer": "^3.2.0",
"electron-icon-builder": "^2.0.1",
"electron-vite": "^2.3.0",
@ -216,6 +225,9 @@
"libsql@npm:^0.4.4": "patch:libsql@npm%3A0.4.7#~/.yarn/patches/libsql-npm-0.4.7-444e260fb1.patch",
"openai@npm:^4.77.0": "patch:openai@npm%3A4.87.3#~/.yarn/patches/openai-npm-4.87.3-2b30a7685f.patch",
"pkce-challenge@npm:^4.1.0": "patch:pkce-challenge@npm%3A4.1.0#~/.yarn/patches/pkce-challenge-npm-4.1.0-fbc51695a3.patch",
"@types/domexception": "^4",
"electron": "22.3.23",
"electron-builder": "^24.9.1",
"app-builder-lib@npm:26.0.13": "patch:app-builder-lib@npm%3A26.0.13#~/.yarn/patches/app-builder-lib-npm-26.0.13-a064c9e1d0.patch",
"shiki": "3.2.2"
},

View File

@ -1,6 +1,7 @@
import { app } from 'electron'
import { getDataPath } from './utils'
import { isWindows7 } from './utils/runtime'
const isDev = process.env.NODE_ENV === 'development'
@ -12,12 +13,12 @@ export const DATA_PATH = getDataPath()
export const titleBarOverlayDark = {
height: 40,
color: 'rgba(0,0,0,0)',
color: isWindows7() ? '#1c1c1c' : 'rgba(0,0,0,0)',
symbolColor: '#ffffff'
}
export const titleBarOverlayLight = {
height: 40,
color: 'rgba(255,255,255,0)',
color: isWindows7() ? '#f4f4f4' : 'rgba(255,255,255,0)',
symbolColor: '#000000'
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,36 @@
console.info('inject polyfill win7')
// fix for node_modules\@libsql\isomorphic-fetch\node.cjs
if (!globalThis.fetch) {
globalThis.fetch = require('node-fetch')
}
if (!globalThis.Request) {
const { Request, Headers } = require('node-fetch')
globalThis.Request = Request
globalThis.Headers = Headers
}
// fix for node_modules/undici/lib/web/fetch/webidl.js
if (!globalThis.Blob) {
const { Blob } = require('blob-polyfill')
globalThis.Blob = Blob
}
// fix for node_modules/undici/lib/web/fetch/webidl.js
if (!globalThis.ReadableStream) {
const { ReadableStream, TransformStream } = require('web-streams-polyfill')
globalThis.ReadableStream = ReadableStream
globalThis.TransformStream = TransformStream
console.log('ReadableStream', ReadableStream)
}
if (!globalThis.DOMException) {
globalThis.DOMException = require('domexception')
}
if (!globalThis.crypto) {
const { Crypto } = require('@peculiar/webcrypto')
globalThis.crypto = new Crypto()
}
console.info('inject polyfill win7 ok')

View File

@ -315,7 +315,7 @@ class FileStorage {
fileName: string,
content: string,
options?: SaveDialogOptions
): Promise<string | null> => {
): Promise<string | null | undefined> => {
try {
const result: SaveDialogReturnValue = await dialog.showSaveDialog({
title: '保存文件',

View File

@ -1,4 +1,8 @@
import { ProxyConfig as _ProxyConfig, session } from 'electron'
// import { ProxyConfig as _ProxyConfig, session } from 'electron'
import { session } from 'electron'
declare type _ProxyConfig = any;
import { socksDispatcher } from 'fetch-socks'
import { getSystemProxy } from 'os-proxy-config'
import { ProxyAgent as GeneralProxyAgent } from 'proxy-agent'

View File

@ -7,6 +7,7 @@ import iconDark from '../../../build/tray_icon_dark.png?asset'
import iconLight from '../../../build/tray_icon_light.png?asset'
import { configManager } from './ConfigManager'
import { windowService } from './WindowService'
import { APP_NAME } from '../../shared/app-meta'
export class TrayService {
private static instance: TrayService
@ -70,7 +71,7 @@ export class TrayService {
this.tray.setContextMenu(contextMenu)
}
this.tray.setToolTip('Cherry Studio')
this.tray.setToolTip(APP_NAME || 'Cherry Studio')
this.tray.on('right-click', () => {
this.tray?.popUpContextMenu(contextMenu)

View File

@ -0,0 +1,7 @@
import os from 'os'
export function isWindows7() {
if (process.platform !== 'win32') return false
const version = os.release()
return version.startsWith('6.1') // Windows 7 的版本号为 6.1
}

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 550 KiB

View File

@ -21,7 +21,8 @@ import { setMinappsOpenLinkExternal } from '@renderer/store/settings'
import { MinAppType } from '@renderer/types'
import { delay } from '@renderer/utils'
import { Avatar, Drawer, Tooltip } from 'antd'
import { WebviewTag } from 'electron'
// import { WebviewTag } from 'electron'
declare type WebviewTag = any
import { useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import BeatLoader from 'react-spinners/BeatLoader'

View File

@ -1,4 +1,5 @@
import { WebviewTag } from 'electron'
// import { WebviewTag } from 'electron'
declare type WebviewTag = any
import { memo, useEffect, useRef } from 'react'
/**

View File

@ -1,5 +1,8 @@
import * as AppMeta from '../../../shared/app-meta'
export { default as UserAvatar } from '@renderer/assets/images/avatar.png'
export { default as AppLogo } from '@renderer/assets/images/logo.png'
export const APP_NAME = 'Cherry Studio'
export const APP_NAME = AppMeta.APP_NAME
export const APP_IS_CUSTOM_PRODUCT = AppMeta.APP_IS_CUSTOM_PRODUCT
export const isLocalAi = false

View File

@ -3,6 +3,7 @@ import KeyvStorage from '@kangfenmao/keyv-storage'
import { startAutoSync } from './services/BackupService'
import { startNutstoreAutoSync } from './services/NutstoreService'
import store from './store'
import { APP_NAME, APP_IS_CUSTOM_PRODUCT } from './config/env'
function initSpinner() {
const spinner = document.getElementById('spinner')
@ -32,3 +33,7 @@ function initAutoSync() {
initSpinner()
initKeyv()
initAutoSync()
if (APP_IS_CUSTOM_PRODUCT) {
document.title = APP_NAME
}

4
src/shared/app-meta.ts Normal file
View File

@ -0,0 +1,4 @@
export const DEFAULT_APP_NAME = 'Cherry Studio'
export const APP_NAME = process.env.CUSTOM_APP_NAME || DEFAULT_APP_NAME
// 是否是定制化产品模式
export const APP_IS_CUSTOM_PRODUCT = APP_NAME !== DEFAULT_APP_NAME

View File

@ -2,6 +2,7 @@
"extends": "@electron-toolkit/tsconfig/tsconfig.node.json",
"include": [
"electron.vite.config.*",
"src/shared/*.ts",
"src/main/**/*",
"src/preload/**/*",
"src/main/env.d.ts",

View File

@ -1,6 +1,7 @@
{
"extends": "@electron-toolkit/tsconfig/tsconfig.web.json",
"include": [
"src/shared/*.ts",
"src/renderer/src/**/*",
"src/preload/*.d.ts",
"local/src/renderer/**/*",

808
yarn.lock

File diff suppressed because it is too large Load Diff