mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-26 20:12:38 +08:00
* refactor(ProviderSettings): streamline API key management and enhance user experience - Refactored the handleProvidersProtocolUrl function to simplify API key handling and improve navigation logic. - Updated the useProviders hook to maintain consistency in provider management. - Enhanced the ApiKeyList component with improved state handling and user feedback for API key validation. - Updated localization files to reflect changes in API key management and user interactions. - Improved styling and layout for better visual consistency across provider settings. * fix(ProviderSettings): enhance confirmation modal title with provider name - Updated the confirmation modal title in the ProvidersList component to include the provider's display name, improving clarity for users during API key management. * update info * udpate line * update line * feat(Protocol): add custom protocol handling for Cherry Studio - Introduced a new protocol handler for 'cherrystudio' in the Electron app, allowing the application to respond to custom URL schemes. - Updated the electron-builder configuration to register the 'cherrystudio' protocol. - Enhanced the main application logic to handle incoming protocol URLs effectively, improving user experience when launching the app via custom links. * feat(ProviderSettings): enhance provider data handling with optional fields - Updated the handleProviderAddKey function to accept optional 'name' and 'type' fields for providers, improving flexibility in provider management. - Adjusted the API key handling logic to utilize these new fields, ensuring a more comprehensive provider configuration. - Enhanced the URL schema documentation to reflect the changes in provider data structure. * delete apikeylist * restore apiService * support utf8 * feat(Protocol): improve URL handling for macOS and Windows - Added caching for the URL received when the app is already running on macOS, ensuring it is processed correctly. - Updated the URL processing logic in handleProvidersProtocolUrl to replace characters for proper decoding. - Simplified base64 decoding in ProviderSettings to enhance readability and maintainability. * fix start in macOS * format code * fix(ProviderSettings): validate provider data before adding - Added validation to ensure 'id', 'newApiKey', and 'baseUrl' are present before proceeding with provider addition. - Implemented error handling to notify users of invalid data and redirect them to the provider settings page. * feat(Protocol): enhance URL processing for versioning - Updated the URL handling logic in handleProvidersProtocolUrl to support versioning by extracting the 'v' parameter. - Added logging for version 1 to facilitate future enhancements in handling different protocol versions. - Improved the processing of the 'data' parameter for better compatibility with the updated URL schema. * feat(i18n): add provider API key management translations for Japanese, Russian, and Traditional Chinese - Introduced new translations for API key management features, including confirmation prompts and error messages related to provider API keys. - Enhanced user experience by providing localized strings for adding, updating, and validating API keys across multiple languages. --------- Co-authored-by: rcadmin <rcadmin@rcadmins-MacBook-Pro-4.local>
128 lines
4.1 KiB
TypeScript
128 lines
4.1 KiB
TypeScript
import { exec } from 'node:child_process'
|
|
import fs from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
import { promisify } from 'node:util'
|
|
|
|
import { app } from 'electron'
|
|
import Logger from 'electron-log'
|
|
|
|
import { handleProvidersProtocolUrl } from './urlschema/handle-providers'
|
|
import { handleMcpProtocolUrl } from './urlschema/mcp-install'
|
|
import { windowService } from './WindowService'
|
|
|
|
export const CHERRY_STUDIO_PROTOCOL = 'cherrystudio'
|
|
|
|
export function registerProtocolClient(app: Electron.App) {
|
|
if (process.defaultApp) {
|
|
if (process.argv.length >= 2) {
|
|
app.setAsDefaultProtocolClient(CHERRY_STUDIO_PROTOCOL, process.execPath, [process.argv[1]])
|
|
}
|
|
}
|
|
|
|
app.setAsDefaultProtocolClient(CHERRY_STUDIO_PROTOCOL)
|
|
}
|
|
|
|
export function handleProtocolUrl(url: string) {
|
|
if (!url) return
|
|
// Process the URL that was used to open the app
|
|
// The url will be in the format: cherrystudio://data?param1=value1¶m2=value2
|
|
|
|
// Parse the URL and extract parameters
|
|
const urlObj = new URL(url)
|
|
const params = new URLSearchParams(urlObj.search)
|
|
|
|
switch (urlObj.hostname.toLowerCase()) {
|
|
case 'mcp':
|
|
handleMcpProtocolUrl(urlObj)
|
|
return
|
|
case 'providers':
|
|
handleProvidersProtocolUrl(urlObj)
|
|
return
|
|
}
|
|
|
|
// You can send the data to your renderer process
|
|
const mainWindow = windowService.getMainWindow()
|
|
|
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
mainWindow.webContents.send('protocol-data', {
|
|
url,
|
|
params: Object.fromEntries(params.entries())
|
|
})
|
|
}
|
|
}
|
|
|
|
const execAsync = promisify(exec)
|
|
|
|
const DESKTOP_FILE_NAME = 'cherrystudio-url-handler.desktop'
|
|
|
|
/**
|
|
* Sets up deep linking for the AppImage build on Linux by creating a .desktop file.
|
|
* This allows the OS to open cherrystudio:// URLs with this App.
|
|
*/
|
|
export async function setupAppImageDeepLink(): Promise<void> {
|
|
// Only run on Linux and when packaged as an AppImage
|
|
if (process.platform !== 'linux' || !process.env.APPIMAGE) {
|
|
return
|
|
}
|
|
|
|
Logger.info('AppImage environment detected on Linux, setting up deep link.')
|
|
|
|
try {
|
|
const appPath = app.getPath('exe')
|
|
if (!appPath) {
|
|
Logger.error('Could not determine App path.')
|
|
return
|
|
}
|
|
|
|
const homeDir = app.getPath('home')
|
|
const applicationsDir = path.join(homeDir, '.local', 'share', 'applications')
|
|
const desktopFilePath = path.join(applicationsDir, DESKTOP_FILE_NAME)
|
|
|
|
// Ensure the applications directory exists
|
|
await fs.mkdir(applicationsDir, { recursive: true })
|
|
|
|
// Content of the .desktop file
|
|
// %U allows passing the URL to the application
|
|
// NoDisplay=true hides it from the regular application menu
|
|
const desktopFileContent = `[Desktop Entry]
|
|
Name=Cherry Studio
|
|
Exec=${escapePathForExec(appPath)} %U
|
|
Terminal=false
|
|
Type=Application
|
|
MimeType=x-scheme-handler/${CHERRY_STUDIO_PROTOCOL};
|
|
NoDisplay=true
|
|
`
|
|
|
|
// Write the .desktop file (overwrite if exists)
|
|
await fs.writeFile(desktopFilePath, desktopFileContent, 'utf-8')
|
|
Logger.info(`Created/Updated desktop file: ${desktopFilePath}`)
|
|
|
|
// Update the desktop database
|
|
// It's important to update the database for the changes to take effect
|
|
try {
|
|
const { stdout, stderr } = await execAsync(`update-desktop-database ${escapePathForExec(applicationsDir)}`)
|
|
if (stderr) {
|
|
Logger.warn(`update-desktop-database stderr: ${stderr}`)
|
|
}
|
|
Logger.info(`update-desktop-database stdout: ${stdout}`)
|
|
Logger.info('Desktop database updated successfully.')
|
|
} catch (updateError) {
|
|
Logger.error('Failed to update desktop database:', updateError)
|
|
// Continue even if update fails, as the file is still created.
|
|
}
|
|
} catch (error) {
|
|
// Log the error but don't prevent the app from starting
|
|
Logger.error('Failed to setup AppImage deep link:', error)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Escapes a path for safe use within the Exec field of a .desktop file
|
|
* and for shell commands. Handles spaces and potentially other special characters
|
|
* by quoting.
|
|
*/
|
|
function escapePathForExec(filePath: string): string {
|
|
// Simple quoting for paths with spaces.
|
|
return `'${filePath.replace(/'/g, "'\\''")}'`
|
|
}
|