Skip to content

Commit 47c0641

Browse files
OrKoNDevtools-frontend LUCI CQ
authored andcommitted
Refactor UserActionRow state management
Bug: none Change-Id: If3b3a8b7b1a1ca80ce2b29b3bd1c792ffd7c4684 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6218893 Reviewed-by: Ergün Erdoğmuş <[email protected]> Commit-Queue: Alex Rudenko <[email protected]>
1 parent c937f0f commit 47c0641

File tree

2 files changed

+63
-88
lines changed

2 files changed

+63
-88
lines changed

front_end/panels/ai_assistance/components/UserActionRow.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
import * as Freestyler from '../ai_assistance.js';
1010

1111
describeWithEnvironment('UserActionRow', () => {
12-
function createComponent(props: Freestyler.UserActionRowProps):
12+
function createComponent(props: Freestyler.UserActionRowWidgetParams):
1313
[sinon.SinonStub<[Freestyler.ViewInput, Freestyler.ViewOutput, HTMLElement], void>, Freestyler.UserActionRow] {
1414
const view = sinon.stub<[Freestyler.ViewInput, Freestyler.ViewOutput, HTMLElement]>();
1515
const component = new Freestyler.UserActionRow(undefined, view);
@@ -29,14 +29,14 @@ describeWithEnvironment('UserActionRow', () => {
2929
assert.isTrue(view.calledOnce);
3030

3131
{
32-
const [viewInput] = view.args[0];
32+
const [viewInput] = view.lastCall.args;
3333
expect(viewInput.isShowingFeedbackForm).equals(false);
3434
viewInput.onRatingClick(Host.AidaClient.Rating.POSITIVE);
3535
}
3636

3737
assert.isTrue(view.calledTwice);
3838
{
39-
const [viewInput] = view.args[0];
39+
const [viewInput] = view.lastCall.args;
4040
expect(viewInput.isShowingFeedbackForm).equals(true);
4141
}
4242
});
@@ -52,14 +52,14 @@ describeWithEnvironment('UserActionRow', () => {
5252
assert.isTrue(view.calledOnce);
5353

5454
{
55-
const [viewInput] = view.args[0];
55+
const [viewInput] = view.lastCall.args;
5656
expect(viewInput.isShowingFeedbackForm).equals(false);
5757
viewInput.onRatingClick(Host.AidaClient.Rating.POSITIVE);
5858
}
5959

6060
assert.isTrue(view.calledTwice);
6161
{
62-
const [viewInput] = view.args[0];
62+
const [viewInput] = view.lastCall.args;
6363
expect(viewInput.isShowingFeedbackForm).equals(false);
6464
}
6565
});
@@ -75,23 +75,23 @@ describeWithEnvironment('UserActionRow', () => {
7575
assert.isTrue(view.calledOnce);
7676

7777
{
78-
const [viewInput] = view.args[0];
78+
const [viewInput] = view.lastCall.args;
7979
expect(viewInput.isSubmitButtonDisabled).equals(false);
8080
viewInput.onRatingClick(Host.AidaClient.Rating.POSITIVE);
8181
}
8282

8383
assert.isTrue(view.calledTwice);
8484

8585
{
86-
const [viewInput] = view.args[0];
86+
const [viewInput] = view.lastCall.args;
8787
expect(viewInput.isSubmitButtonDisabled).equals(false);
8888
expect(viewInput.isShowingFeedbackForm).equals(true);
8989
viewInput.onInputChange('test');
9090
viewInput.onSubmit(new SubmitEvent('submit'));
9191
}
9292

9393
{
94-
const [viewInput] = view.args[0];
94+
const [viewInput] = view.lastCall.args;
9595
expect(viewInput.isSubmitButtonDisabled).equals(true);
9696
}
9797
});

front_end/panels/ai_assistance/components/UserActionRow.ts

Lines changed: 55 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,6 @@ const REPORT_URL = 'https://support.google.com/legal/troubleshooter/1114905?hl=e
7373
Platform.DevToolsPath.UrlString;
7474
const SCROLL_ROUNDING_OFFSET = 1;
7575

76-
export interface UserActionRowProps {
77-
showRateButtons: boolean;
78-
onFeedbackSubmit: (rate: Host.AidaClient.Rating, feedback?: string) => void;
79-
suggestions?: [string, ...string[]];
80-
onSuggestionClick: (suggestion: string) => void;
81-
canShowFeedbackForm: boolean;
82-
}
83-
84-
interface State {
85-
onFeedbackSubmit?: (rate: Host.AidaClient.Rating, feedback?: string) => void;
86-
canShowFeedbackForm: boolean;
87-
}
88-
8976
export interface RatingViewInput {
9077
currentRating?: Host.AidaClient.Rating;
9178
onRatingClick: (rating: Host.AidaClient.Rating) => void;
@@ -116,49 +103,46 @@ export interface ViewOutput {
116103
suggestionsRightScrollButtonContainer?: Element;
117104
}
118105

106+
export interface UserActionRowWidgetParams {
107+
showRateButtons: boolean;
108+
onFeedbackSubmit: (rate: Host.AidaClient.Rating, feedback?: string) => void;
109+
suggestions?: [string, ...string[]];
110+
onSuggestionClick: (suggestion: string) => void;
111+
canShowFeedbackForm: boolean;
112+
}
113+
119114
export type View = (input: ViewInput, output: ViewOutput, target: HTMLElement) => void;
120115

121116
/**
122117
* This presenter has too many responsibilities (rating buttons, feedback
123118
* form, suggestions).
124119
*/
125-
export class UserActionRow extends UI.Widget.Widget implements UserActionRowProps {
126-
#state: State = {
127-
canShowFeedbackForm: false,
128-
};
120+
export class UserActionRow extends UI.Widget.Widget implements UserActionRowWidgetParams {
121+
showRateButtons = false;
122+
onFeedbackSubmit: (rate: Host.AidaClient.Rating, feedback?: string) => void = () => {};
123+
suggestions: [string, ...string[]]|undefined;
124+
onSuggestionClick: (suggestion: string) => void = () => {};
125+
canShowFeedbackForm = false;
126+
129127
#suggestionsResizeObserver = new ResizeObserver(() => this.#handleSuggestionsScrollOrResize());
130128
#suggestionsEvaluateLayoutThrottler = new Common.Throttler.Throttler(50);
129+
130+
#feedbackValue = '';
131+
#currentRating: Host.AidaClient.Rating|undefined;
132+
#isShowingFeedbackForm = false;
133+
#isSubmitButtonDisabled = false;
134+
131135
#view: View;
132-
#viewInput: ViewInput = {
133-
currentRating: undefined,
134-
onRatingClick: this.#handleRateClick.bind(this),
135-
showRateButtons: true,
136-
onReportClick: () => Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(REPORT_URL),
137-
138-
suggestions: undefined,
139-
scrollSuggestionsScrollContainer: this.#scrollSuggestionsScrollContainer.bind(this),
140-
onSuggestionsScrollOrResize: this.#handleSuggestionsScrollOrResize.bind(this),
141-
onSuggestionClick: () => {},
142-
143-
isShowingFeedbackForm: false,
144-
onSubmit: this.#handleSubmit.bind(this),
145-
onClose: this.#handleClose.bind(this),
146-
onInputChange: this.#handleInputChange.bind(this),
147-
isSubmitButtonDisabled: false,
148-
};
149136
#viewOutput: ViewOutput = {};
150-
#feedbackValue = '';
151137

152138
constructor(element?: HTMLElement, view?: View) {
153139
super(false, false, element);
154140
this.registerRequiredCSS(Input.textInputStylesRaw);
141+
this.registerRequiredCSS(userActionRowStyles);
155142
// clang-format off
156143
this.#view = view ?? ((input, output, target) => {
157144
Lit.render(
158145
html`
159-
<style>
160-
${userActionRowStyles.cssContent}
161-
</style>
162146
<div class="ai-assistance-feedback-row">
163147
${renderButtons(input)}
164148
${renderSuggestions(input, output)}
@@ -173,31 +157,6 @@ export class UserActionRow extends UI.Widget.Widget implements UserActionRowProp
173157
// clang-format on
174158
}
175159

176-
set showRateButtons(value: boolean) {
177-
this.#viewInput.showRateButtons = value;
178-
this.requestUpdate();
179-
}
180-
181-
set onFeedbackSubmit(value: (rate: Host.AidaClient.Rating, feedback?: string) => void) {
182-
this.#state.onFeedbackSubmit = value;
183-
this.requestUpdate();
184-
}
185-
186-
set suggestions(suggestions: [string, ...string[]]|undefined) {
187-
this.#viewInput.suggestions = suggestions;
188-
this.requestUpdate();
189-
}
190-
191-
set onSuggestionClick(callback: (suggestion: string) => void) {
192-
this.#viewInput.onSuggestionClick = callback;
193-
this.requestUpdate();
194-
}
195-
196-
set canShowFeedbackForm(value: boolean) {
197-
this.#state.canShowFeedbackForm = value;
198-
this.requestUpdate();
199-
}
200-
201160
override wasShown(): void {
202161
super.wasShown();
203162
void this.performUpdate();
@@ -209,14 +168,30 @@ export class UserActionRow extends UI.Widget.Widget implements UserActionRowProp
209168
}
210169

211170
override performUpdate(): Promise<void>|void {
212-
this.#view(this.#viewInput, this.#viewOutput, this.contentElement);
171+
this.#view(
172+
{
173+
onSuggestionClick: this.onSuggestionClick,
174+
onRatingClick: this.#handleRateClick.bind(this),
175+
onReportClick: () => Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(REPORT_URL),
176+
scrollSuggestionsScrollContainer: this.#scrollSuggestionsScrollContainer.bind(this),
177+
onSuggestionsScrollOrResize: this.#handleSuggestionsScrollOrResize.bind(this),
178+
onSubmit: this.#handleSubmit.bind(this),
179+
onClose: this.#handleClose.bind(this),
180+
onInputChange: this.#handleInputChange.bind(this),
181+
isSubmitButtonDisabled: this.#isSubmitButtonDisabled,
182+
showRateButtons: this.showRateButtons,
183+
suggestions: this.suggestions,
184+
currentRating: this.#currentRating,
185+
isShowingFeedbackForm: this.#isShowingFeedbackForm,
186+
},
187+
this.#viewOutput, this.contentElement);
213188
}
214189

215190
#handleInputChange(value: string): void {
216191
this.#feedbackValue = value;
217192
const disableSubmit = !value;
218-
if (disableSubmit !== this.#viewInput.isSubmitButtonDisabled) {
219-
this.#viewInput.isSubmitButtonDisabled = disableSubmit;
193+
if (disableSubmit !== this.#isSubmitButtonDisabled) {
194+
this.#isSubmitButtonDisabled = disableSubmit;
220195
void this.performUpdate();
221196
}
222197
}
@@ -263,37 +238,37 @@ export class UserActionRow extends UI.Widget.Widget implements UserActionRowProp
263238
}
264239

265240
#handleRateClick(rating: Host.AidaClient.Rating): void {
266-
if (this.#viewInput.currentRating === rating) {
267-
this.#viewInput.currentRating = undefined;
268-
this.#viewInput.isShowingFeedbackForm = false;
269-
this.#viewInput.isSubmitButtonDisabled = true;
241+
if (this.#currentRating === rating) {
242+
this.#currentRating = undefined;
243+
this.#isShowingFeedbackForm = false;
244+
this.#isSubmitButtonDisabled = true;
270245
// This effectively reset the user rating
271-
this.#state.onFeedbackSubmit?.(Host.AidaClient.Rating.SENTIMENT_UNSPECIFIED);
246+
this.onFeedbackSubmit(Host.AidaClient.Rating.SENTIMENT_UNSPECIFIED);
272247
void this.performUpdate();
273248
return;
274249
}
275250

276-
this.#viewInput.currentRating = rating;
277-
this.#viewInput.isShowingFeedbackForm = this.#state.canShowFeedbackForm;
278-
this.#state.onFeedbackSubmit?.(rating);
251+
this.#currentRating = rating;
252+
this.#isShowingFeedbackForm = this.canShowFeedbackForm;
253+
this.onFeedbackSubmit(rating);
279254
void this.performUpdate();
280255
}
281256

282257
#handleClose(): void {
283-
this.#viewInput.isShowingFeedbackForm = false;
284-
this.#viewInput.isSubmitButtonDisabled = true;
258+
this.#isShowingFeedbackForm = false;
259+
this.#isSubmitButtonDisabled = true;
285260
void this.performUpdate();
286261
}
287262

288263
#handleSubmit(ev: SubmitEvent): void {
289264
ev.preventDefault();
290265
const input = this.#feedbackValue;
291-
if (!this.#viewInput.currentRating || !input) {
266+
if (!this.#currentRating || !input) {
292267
return;
293268
}
294-
this.#state.onFeedbackSubmit?.(this.#viewInput.currentRating, input);
295-
this.#viewInput.isShowingFeedbackForm = false;
296-
this.#viewInput.isSubmitButtonDisabled = true;
269+
this.onFeedbackSubmit(this.#currentRating, input);
270+
this.#isShowingFeedbackForm = false;
271+
this.#isSubmitButtonDisabled = true;
297272
void this.performUpdate();
298273
}
299274
}

0 commit comments

Comments
 (0)