chore(app-identity): rebrand bundle id to com.cherryai.CherryStudio

Rename the app bundle id from com.kangfenmao.CherryStudio to
com.cherryai.CherryStudio at every definition point: electron-builder
appId (packaging source of truth), macOS notarization appBundleId,
Windows AppUserModelID, and the selection self-detection allowlist.

Daily preview builds now use com.cherryai.CherryStudio.preview (a distinct
channel id rather than a case-only variant that macOS would treat as the
same app); the workflow replaceAll search strings are updated to the new
id so the preview identity patch keeps matching.

Incidental cleanups bundled in:
- Drop the unused MAIN_VITE_BUNDLE_ID env override; env.d.ts now declares
  the actually-used MAIN_VITE_CHERRYAI_CLIENT_SECRET instead of leaning on
  vite/client's any index signature.
- Remove the stale @kangfenmao/keyv-storage from pnpm.onlyBuiltDependencies.
- SearchService: use @main/core/platform isDev over electron-toolkit is.dev.
This commit is contained in:
fullex
2026-05-27 08:31:22 -07:00
parent aca7e40800
commit 4439d3b283
8 changed files with 15 additions and 19 deletions

View File

@@ -122,20 +122,20 @@ jobs:
path: 'electron-builder.yml',
replace: (content) =>
content
.replace(/^appId: .+$/m, 'appId: com.cherryai.cherrystudio')
.replace(/^appId: .+$/m, 'appId: com.cherryai.CherryStudio.preview')
.replace(/^productName: .+$/m, 'productName: Cherry Studio Next')
},
{
path: 'scripts/notarize.js',
replace: (content) => content.replaceAll('com.kangfenmao.CherryStudio', 'com.cherryai.cherrystudio')
replace: (content) => content.replaceAll('com.cherryai.CherryStudio', 'com.cherryai.CherryStudio.preview')
},
{
path: 'src/main/index.ts',
replace: (content) => content.replaceAll('com.kangfenmao.CherryStudio', 'com.cherryai.cherrystudio')
replace: (content) => content.replaceAll('com.cherryai.CherryStudio', 'com.cherryai.CherryStudio.preview')
},
{
path: 'src/main/services/selection/SelectionService.ts',
replace: (content) => content.replaceAll('com.kangfenmao.CherryStudio', 'com.cherryai.cherrystudio')
replace: (content) => content.replaceAll('com.cherryai.CherryStudio', 'com.cherryai.CherryStudio.preview')
}
]

View File

@@ -1,4 +1,4 @@
appId: com.kangfenmao.CherryStudio
appId: com.cherryai.CherryStudio
productName: Cherry Studio
electronLanguages:
- zh-CN

View File

@@ -522,7 +522,6 @@
},
"onlyBuiltDependencies": [
"@j178/prek",
"@kangfenmao/keyv-storage",
"@paymoapp/electron-shutdown-handler",
"@scarf/scarf",
"@swc/core",

View File

@@ -15,7 +15,7 @@ exports.default = async function notarizing(context) {
await notarize({
appPath,
appBundleId: 'com.kangfenmao.CherryStudio',
appBundleId: 'com.cherryai.CherryStudio',
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_APP_SPECIFIC_PASSWORD,
teamId: process.env.APPLE_TEAM_ID

8
src/main/env.d.ts vendored
View File

@@ -1,9 +1,3 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
VITE_MAIN_BUNDLE_ID: string
}
interface ImportMeta {
readonly env: ImportMetaEnv
readonly MAIN_VITE_CHERRYAI_CLIENT_SECRET: string
}

View File

@@ -41,8 +41,11 @@ const startApp = async () => {
const migrationResult = await runV2MigrationGate()
if (migrationResult === 'handled') return
// TODO(v2): move to a lifecycle service — here temporarily for timing.
electronApp.setAppUserModelId(import.meta.env.VITE_MAIN_BUNDLE_ID || 'com.kangfenmao.CherryStudio')
// Set the Windows AppUserModelID — the identity Windows uses to attribute this
// app's notifications, taskbar icon grouping, and Jump Lists (no-op on macOS/Linux).
// Must run before any window is created or notification fires, hence after the
// migration gate returns and before lifecycle bootstrap.
electronApp.setAppUserModelId('com.cherryai.CherryStudio')
// Start lifecycle (BeforeReady runs parallel with app.whenReady)
application.registerAll(serviceList)

View File

@@ -1,6 +1,6 @@
import { is } from '@electron-toolkit/utils'
import { loggerService } from '@logger'
import { BaseService, Injectable, Phase, ServicePhase } from '@main/core/lifecycle'
import { isDev } from '@main/core/platform'
import { IpcChannel } from '@shared/IpcChannel'
import { BrowserWindow } from 'electron'
@@ -42,7 +42,7 @@ export class SearchService extends BaseService {
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
devTools: is.dev
devTools: isDev
}
})

View File

@@ -570,7 +570,7 @@ export class SelectionService extends BaseService implements Activatable {
// [macOS] a hacky way
// when set `skipTransformProcessType: true`, if the selection is in self app, it will make the selection canceled after toolbar showing
// so we just don't set `skipTransformProcessType: true` when in self app
const isSelf = ['com.github.Electron', 'com.kangfenmao.CherryStudio'].includes(programName)
const isSelf = ['com.github.Electron', 'com.cherryai.CherryStudio'].includes(programName)
if (!isSelf) {
// [macOS] an ugly hacky way