add volume setting

This commit is contained in:
Justin Quan
2024-12-15 23:22:44 -08:00
parent 09934e20f7
commit 1adc36a292
8 changed files with 78 additions and 17 deletions

6
package-lock.json generated
View File

@@ -38,6 +38,7 @@
"puppeteer-chromium-resolver": "^23.0.0",
"puppeteer-core": "^23.4.0",
"serialize-error": "^11.0.3",
"sound-play": "^1.1.0",
"strip-ansi": "^7.1.0",
"tree-sitter-wasms": "^0.1.11",
"turndown": "^7.2.0",
@@ -14001,6 +14002,11 @@
"node": ">= 14"
}
},
"node_modules/sound-play": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/sound-play/-/sound-play-1.1.0.tgz",
"integrity": "sha512-Bd/L0AoCwITFeOnpNLMsfPXrV5GG5NhrC/T6odveahYbhPZkdTnrFXRia9FCC5WBWdUTw1d+yvLBvi4wnD1xOA=="
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",

View File

@@ -220,6 +220,7 @@
"puppeteer-chromium-resolver": "^23.0.0",
"puppeteer-core": "^23.4.0",
"serialize-error": "^11.0.3",
"sound-play": "^1.1.0",
"strip-ansi": "^7.1.0",
"tree-sitter-wasms": "^0.1.11",
"turndown": "^7.2.0",

View File

@@ -22,7 +22,7 @@ import { Cline } from "../Cline"
import { openMention } from "../mentions"
import { getNonce } from "./getNonce"
import { getUri } from "./getUri"
import { playSound, setSoundEnabled } from "../../utils/sound"
import { playSound, setSoundEnabled, setSoundVolume } from "../../utils/sound"
/*
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
@@ -66,6 +66,7 @@ type GlobalStateKey =
| "openRouterUseMiddleOutTransform"
| "allowedCommands"
| "soundEnabled"
| "soundVolume"
| "diffEnabled"
| "alwaysAllowMcp"
@@ -597,6 +598,12 @@ export class ClineProvider implements vscode.WebviewViewProvider {
setSoundEnabled(soundEnabled) // Add this line to update the sound utility
await this.postStateToWebview()
break
case "soundVolume":
const soundVolume = message.value ?? 0.5
await this.updateGlobalState("soundVolume", soundVolume)
setSoundVolume(soundVolume)
await this.postStateToWebview()
break
case "diffEnabled":
const diffEnabled = message.bool ?? true
await this.updateGlobalState("diffEnabled", diffEnabled)
@@ -929,6 +936,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
soundEnabled,
diffEnabled,
taskHistory,
soundVolume,
} = await this.getState()
const allowedCommands = vscode.workspace
@@ -953,6 +961,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
diffEnabled: diffEnabled ?? false,
shouldShowAnnouncement: lastShownAnnouncementId !== this.latestAnnouncementId,
allowedCommands,
soundVolume: soundVolume ?? 0.5,
}
}
@@ -1045,6 +1054,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
allowedCommands,
soundEnabled,
diffEnabled,
soundVolume,
] = await Promise.all([
this.getGlobalState("apiProvider") as Promise<ApiProvider | undefined>,
this.getGlobalState("apiModelId") as Promise<string | undefined>,
@@ -1082,6 +1092,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
this.getGlobalState("allowedCommands") as Promise<string[] | undefined>,
this.getGlobalState("soundEnabled") as Promise<boolean | undefined>,
this.getGlobalState("diffEnabled") as Promise<boolean | undefined>,
this.getGlobalState("soundVolume") as Promise<number | undefined>,
])
let apiProvider: ApiProvider
@@ -1137,6 +1148,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
allowedCommands,
soundEnabled,
diffEnabled,
soundVolume,
}
}

View File

@@ -51,6 +51,7 @@ export interface ExtensionState {
uriScheme?: string
allowedCommands?: string[]
soundEnabled?: boolean
soundVolume?: number
diffEnabled?: boolean
}

View File

@@ -32,6 +32,7 @@ export interface WebviewMessage {
| "alwaysAllowMcp"
| "playSound"
| "soundEnabled"
| "soundVolume"
| "diffEnabled"
| "openMcpSettings"
| "restartMcpServer"
@@ -43,6 +44,7 @@ export interface WebviewMessage {
apiConfiguration?: ApiConfiguration
images?: string[]
bool?: boolean
value?: number
commands?: string[]
audioType?: AudioType
// For toggleToolAutoApprove

View File

@@ -21,6 +21,7 @@ export const isWAV = (filepath: string): boolean => {
}
let isSoundEnabled = false
let volume = .5
/**
* Set sound configuration
@@ -30,6 +31,14 @@ export const setSoundEnabled = (enabled: boolean): void => {
isSoundEnabled = enabled
}
/**
* Set sound volume
* @param volume number
*/
export const setSoundVolume = (newVolume: number): void => {
volume = newVolume
}
/**
* Play a sound file
* @param filepath string
@@ -54,11 +63,9 @@ export const playSound = (filepath: string): void => {
return // Skip playback within minimum interval to prevent continuous playback
}
const player = require("play-sound")()
player.play(filepath, function (err: any) {
if (err) {
const sound = require("sound-play")
sound.play(filepath, volume).catch(() => {
throw new Error("Failed to play sound effect")
}
})
lastPlayedTime = currentTime

View File

@@ -29,6 +29,8 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
setAlwaysAllowMcp,
soundEnabled,
setSoundEnabled,
soundVolume,
setSoundVolume,
diffEnabled,
setDiffEnabled,
openRouterModels,
@@ -55,6 +57,7 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
vscode.postMessage({ type: "alwaysAllowMcp", bool: alwaysAllowMcp })
vscode.postMessage({ type: "allowedCommands", commands: allowedCommands ?? [] })
vscode.postMessage({ type: "soundEnabled", bool: soundEnabled })
vscode.postMessage({ type: "soundVolume", value: soundVolume })
vscode.postMessage({ type: "diffEnabled", bool: diffEnabled })
onDone()
}
@@ -306,6 +309,7 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
<h4 style={{ fontWeight: 500, marginBottom: 10 }}>Experimental Features</h4>
<div style={{ marginBottom: 5 }}>
<div style={{ marginBottom: 10 }}>
<VSCodeCheckbox checked={soundEnabled} onChange={(e: any) => setSoundEnabled(e.target.checked)}>
<span style={{ fontWeight: "500" }}>Enable sound effects</span>
</VSCodeCheckbox>
@@ -318,6 +322,30 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
When enabled, Cline will play sound effects for notifications and events.
</p>
</div>
{soundEnabled && (
<div style={{ marginLeft: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '5px' }}>
<span style={{ fontWeight: "500", minWidth: '50px' }}>Volume</span>
<input
type="range"
min="0"
max="1"
step="0.01"
value={soundVolume ?? 0.5}
onChange={(e) => setSoundVolume(parseFloat(e.target.value))}
style={{
flexGrow: 1,
accentColor: 'var(--vscode-button-background)',
height: '2px'
}}
/>
<span style={{ minWidth: '35px', textAlign: 'left' }}>
{Math.round((soundVolume ?? 0.5) * 100)}%
</span>
</div>
</div>
)}
</div>
</div>
{IS_DEV && (

View File

@@ -29,6 +29,7 @@ export interface ExtensionStateContextType extends ExtensionState {
setShowAnnouncement: (value: boolean) => void
setAllowedCommands: (value: string[]) => void
setSoundEnabled: (value: boolean) => void
setSoundVolume: (value: number) => void
setDiffEnabled: (value: boolean) => void
}
@@ -42,6 +43,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
shouldShowAnnouncement: false,
allowedCommands: [],
soundEnabled: false,
soundVolume: 0.5,
diffEnabled: false,
})
const [didHydrateState, setDidHydrateState] = useState(false)
@@ -129,6 +131,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
openRouterModels,
mcpServers,
filePaths,
soundVolume: state.soundVolume,
setApiConfiguration: (value) => setState((prevState) => ({ ...prevState, apiConfiguration: value })),
setCustomInstructions: (value) => setState((prevState) => ({ ...prevState, customInstructions: value })),
setAlwaysAllowReadOnly: (value) => setState((prevState) => ({ ...prevState, alwaysAllowReadOnly: value })),
@@ -139,6 +142,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
setShowAnnouncement: (value) => setState((prevState) => ({ ...prevState, shouldShowAnnouncement: value })),
setAllowedCommands: (value) => setState((prevState) => ({ ...prevState, allowedCommands: value })),
setSoundEnabled: (value) => setState((prevState) => ({ ...prevState, soundEnabled: value })),
setSoundVolume: (value) => setState((prevState) => ({ ...prevState, soundVolume: value })),
setDiffEnabled: (value) => setState((prevState) => ({ ...prevState, diffEnabled: value })),
}