@@ -70,6 +70,101 @@ function isKnownToggle(key: string) {
7070 return toggles . some ( ( entry ) => entry . key === key ) ;
7171}
7272
73+ /**
74+ * The effects {@link handlePanelMessage} is allowed to have.
75+ *
76+ * Injecting them is what separates deciding from doing: the webview supplies
77+ * the real configuration writes, a test supplies recorders.
78+ */
79+ export interface PanelMessageDeps {
80+ isColorKey ( key : string ) : boolean ;
81+ isToggleKey ( key : string ) : boolean ;
82+ save ( key : string , value : string | boolean , scope : string ) : Promise < void > ;
83+ refresh ( ) : void ;
84+ postState ( ) : void ;
85+ }
86+
87+ /**
88+ * Act on one message from the settings webview.
89+ *
90+ * Unknown keys and malformed messages are dropped without any effect at all,
91+ * so a webview that has drifted from the extension cannot write a setting the
92+ * panel does not offer.
93+ *
94+ * @param message whatever the webview posted, which is not to be trusted
95+ * @param deps the key vocabulary and the effects to perform
96+ */
97+ export async function handlePanelMessage (
98+ message : unknown ,
99+ deps : PanelMessageDeps
100+ ) : Promise < void > {
101+ if ( ! message || typeof message !== "object" ) {
102+ return ;
103+ }
104+ const panelMessage = message as PanelMessage ;
105+ if ( panelMessage . type === "applyAll" ) {
106+ for ( const { key, value } of getPendingPreviews ( ) ) {
107+ if ( deps . isColorKey ( key ) || deps . isToggleKey ( key ) ) {
108+ await deps . save ( key , value , panelMessage . scope ) ;
109+ }
110+ }
111+ clearAllPreviews ( ) ;
112+ deps . refresh ( ) ;
113+ deps . postState ( ) ;
114+ return ;
115+ }
116+ if ( panelMessage . type === "resetAll" ) {
117+ // Toggles go too: a pending switch is a preview like any other, and
118+ // "reset all" that left one standing would not have reset the panel.
119+ clearAllPreviews ( ) ;
120+ deps . refresh ( ) ;
121+ deps . postState ( ) ;
122+ return ;
123+ }
124+ if ( panelMessage . type === "resetRow" ) {
125+ if ( ! deps . isColorKey ( panelMessage . key ) ) {
126+ return ;
127+ }
128+ clearPreview ( panelMessage . key ) ;
129+ deps . refresh ( ) ;
130+ deps . postState ( ) ;
131+ return ;
132+ }
133+ if (
134+ panelMessage . type === "previewToggle" ||
135+ panelMessage . type === "applyToggle"
136+ ) {
137+ if ( ! deps . isToggleKey ( panelMessage . key ) ) {
138+ return ;
139+ }
140+ const value = panelMessage . value === true ;
141+ if ( panelMessage . type === "previewToggle" ) {
142+ setPreviewToggle ( panelMessage . key , value ) ;
143+ deps . refresh ( ) ;
144+ return ;
145+ }
146+ clearPreview ( panelMessage . key ) ;
147+ await deps . save ( panelMessage . key , value , panelMessage . scope ) ;
148+ deps . refresh ( ) ;
149+ deps . postState ( ) ;
150+ return ;
151+ }
152+ if ( ! deps . isColorKey ( panelMessage . key ) ) {
153+ return ;
154+ }
155+ if ( panelMessage . type === "preview" ) {
156+ setPreviewColor ( panelMessage . key , panelMessage . value ) ;
157+ deps . refresh ( ) ;
158+ return ;
159+ }
160+ if ( panelMessage . type === "apply" ) {
161+ clearPreview ( panelMessage . key ) ;
162+ await deps . save ( panelMessage . key , panelMessage . value , panelMessage . scope ) ;
163+ deps . refresh ( ) ;
164+ deps . postState ( ) ;
165+ }
166+ }
167+
73168let resolvedHtml : string | undefined ;
74169let resolvedView : vscode . WebviewView | undefined ;
75170
@@ -185,67 +280,13 @@ class ColorPanelProvider implements vscode.WebviewViewProvider {
185280 }
186281
187282 private async handle ( message : PanelMessage ) {
188- if ( ! message ) {
189- return ;
190- }
191- if ( message . type === "applyAll" ) {
192- for ( const { key, value } of getPendingPreviews ( ) ) {
193- if ( isKnownKey ( key ) || isKnownToggle ( key ) ) {
194- await this . save ( key , value , message . scope ) ;
195- }
196- }
197- clearAllPreviews ( ) ;
198- this . refresh ( ) ;
199- this . postState ( ) ;
200- return ;
201- }
202- if ( message . type === "resetAll" ) {
203- // Toggles go too: a pending switch is a preview like any other, and
204- // "reset all" that left one standing would not have reset the panel.
205- clearAllPreviews ( ) ;
206- this . refresh ( ) ;
207- this . postState ( ) ;
208- return ;
209- }
210- if ( message . type === "resetRow" ) {
211- if ( ! isKnownKey ( message . key ) ) {
212- return ;
213- }
214- clearPreview ( message . key ) ;
215- this . refresh ( ) ;
216- this . postState ( ) ;
217- return ;
218- }
219- if ( message . type === "previewToggle" || message . type === "applyToggle" ) {
220- if ( ! isKnownToggle ( message . key ) ) {
221- return ;
222- }
223- const value = message . value === true ;
224- if ( message . type === "previewToggle" ) {
225- setPreviewToggle ( message . key , value ) ;
226- this . refresh ( ) ;
227- return ;
228- }
229- clearPreview ( message . key ) ;
230- await this . save ( message . key , value , message . scope ) ;
231- this . refresh ( ) ;
232- this . postState ( ) ;
233- return ;
234- }
235- if ( ! isKnownKey ( message . key ) ) {
236- return ;
237- }
238- if ( message . type === "preview" ) {
239- setPreviewColor ( message . key , message . value ) ;
240- this . refresh ( ) ;
241- return ;
242- }
243- if ( message . type === "apply" ) {
244- clearPreview ( message . key ) ;
245- await this . save ( message . key , message . value , message . scope ) ;
246- this . refresh ( ) ;
247- this . postState ( ) ;
248- }
283+ await handlePanelMessage ( message , {
284+ isColorKey : isKnownKey ,
285+ isToggleKey : isKnownToggle ,
286+ save : ( key , value , scope ) => this . save ( key , value , scope ) ,
287+ refresh : ( ) => this . refresh ( ) ,
288+ postState : ( ) => this . postState ( ) ,
289+ } ) ;
249290 }
250291}
251292
0 commit comments