@@ -62,15 +62,42 @@ function updateEventSoundConfig(
6262 } ;
6363}
6464
65+ function collectManagedAssetIds ( settings : EventSoundSettings ) : Set < string > {
66+ const managedAssetIds = new Set < string > ( ) ;
67+
68+ for ( const config of Object . values ( settings ?? { } ) ) {
69+ if ( config ?. source ?. kind === "managed" ) {
70+ managedAssetIds . add ( config . source . assetId ) ;
71+ }
72+ }
73+
74+ return managedAssetIds ;
75+ }
76+
77+ function getUnreferencedManagedAssetIds (
78+ previousSettings : EventSoundSettings ,
79+ nextSettings : EventSoundSettings
80+ ) : string [ ] {
81+ const previousAssetIds = collectManagedAssetIds ( previousSettings ) ;
82+ const nextAssetIds = collectManagedAssetIds ( nextSettings ) ;
83+
84+ return [ ...previousAssetIds ] . filter ( ( assetId ) => ! nextAssetIds . has ( assetId ) ) ;
85+ }
86+
6587export function SoundsSection ( ) {
6688 const { api } = useAPI ( ) ;
6789 const [ eventSoundSettings , setEventSoundSettings ] = useState < EventSoundSettings > ( undefined ) ;
6890
6991 const loadNonceRef = useRef ( 0 ) ;
7092 const saveChainRef = useRef < Promise < void > > ( Promise . resolve ( ) ) ;
71- const pendingSettingsRef = useRef < { hasPending : boolean ; settings : EventSoundSettings } > ( {
93+ const pendingSettingsRef = useRef < {
94+ hasPending : boolean ;
95+ settings : EventSoundSettings ;
96+ staleManagedAssetIds : Set < string > ;
97+ } > ( {
7298 hasPending : false ,
7399 settings : undefined ,
100+ staleManagedAssetIds : new Set < string > ( ) ,
74101 } ) ;
75102
76103 // Browser mode uses one hidden file input for all rows, so we track which event key opened it.
@@ -98,14 +125,23 @@ export function SoundsSection() {
98125 } ) ;
99126 } , [ api ] ) ;
100127
101- const queueSettingsSave = ( nextSettings : EventSoundSettings ) => {
128+ const queueSettingsSave = ( nextSettings : EventSoundSettings , staleManagedAssetIds : string [ ] ) => {
102129 if ( ! api ?. config ?. updateEventSoundSettings ) {
103130 return ;
104131 }
105132
106133 pendingSettingsRef . current . hasPending = true ;
107134 pendingSettingsRef . current . settings = nextSettings ;
108135
136+ for ( const staleAssetId of staleManagedAssetIds ) {
137+ pendingSettingsRef . current . staleManagedAssetIds . add ( staleAssetId ) ;
138+ }
139+
140+ // If a pending save now references an asset again, do not delete it.
141+ for ( const referencedAssetId of collectManagedAssetIds ( nextSettings ) ) {
142+ pendingSettingsRef . current . staleManagedAssetIds . delete ( referencedAssetId ) ;
143+ }
144+
109145 // Serialize writes so rapid toggles/file selections cannot persist out-of-order settings.
110146 saveChainRef . current = saveChainRef . current
111147 . catch ( ( ) => {
@@ -118,11 +154,22 @@ export function SoundsSection() {
118154 }
119155
120156 const pendingSettings = pendingSettingsRef . current . settings ;
157+ const staleAssetIds = [ ...pendingSettingsRef . current . staleManagedAssetIds ] ;
121158 pendingSettingsRef . current . hasPending = false ;
159+ pendingSettingsRef . current . staleManagedAssetIds . clear ( ) ;
122160
123161 try {
124162 await api . config . updateEventSoundSettings ( { eventSoundSettings : pendingSettings } ) ;
163+
164+ const deleteAsset = api . eventSounds ?. deleteAsset ;
165+ if ( deleteAsset ) {
166+ const deletePromises = staleAssetIds . map ( ( assetId ) => deleteAsset ( { assetId } ) ) ;
167+ await Promise . allSettled ( deletePromises ) ;
168+ }
125169 } catch {
170+ for ( const staleAssetId of staleAssetIds ) {
171+ pendingSettingsRef . current . staleManagedAssetIds . add ( staleAssetId ) ;
172+ }
126173 // Best-effort only.
127174 }
128175 }
@@ -135,7 +182,8 @@ export function SoundsSection() {
135182
136183 setEventSoundSettings ( ( prev ) => {
137184 const next = updater ( prev ) ;
138- queueSettingsSave ( next ) ;
185+ const staleManagedAssetIds = getUnreferencedManagedAssetIds ( prev , next ) ;
186+ queueSettingsSave ( next , staleManagedAssetIds ) ;
139187 window . dispatchEvent (
140188 createCustomEvent ( CUSTOM_EVENTS . EVENT_SOUND_SETTINGS_CHANGED , {
141189 eventSoundSettings : next ,
0 commit comments