| /** |
| * @license |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| import '@polymer/iron-input/iron-input'; |
| import '../../../styles/shared-styles'; |
| import '../gr-button/gr-button'; |
| import '../gr-select/gr-select'; |
| import {DiffPreferencesInfo, IgnoreWhitespaceType} from '../../../types/diff'; |
| import {getAppContext} from '../../../services/app-context'; |
| import {subscribe} from '../../lit/subscription-controller'; |
| import {formStyles} from '../../../styles/gr-form-styles'; |
| import {sharedStyles} from '../../../styles/shared-styles'; |
| import {LitElement, html} from 'lit'; |
| import {customElement, query, state} from 'lit/decorators'; |
| import {convertToString} from '../../../utils/string-util'; |
| import {fire} from '../../../utils/event-util'; |
| import {ValueChangedEvent} from '../../../types/events'; |
| import {GrSelect} from '../gr-select/gr-select'; |
| |
| @customElement('gr-diff-preferences') |
| export class GrDiffPreferences extends LitElement { |
| @query('#contextLineSelect') private contextLineSelect?: HTMLInputElement; |
| |
| @query('#columnsInput') private columnsInput?: HTMLInputElement; |
| |
| @query('#tabSizeInput') private tabSizeInput?: HTMLInputElement; |
| |
| @query('#fontSizeInput') private fontSizeInput?: HTMLInputElement; |
| |
| @query('#lineWrappingInput') private lineWrappingInput?: HTMLInputElement; |
| |
| @query('#showTabsInput') private showTabsInput?: HTMLInputElement; |
| |
| @query('#showTrailingWhitespaceInput') |
| private showTrailingWhitespaceInput?: HTMLInputElement; |
| |
| @query('#automaticReviewInput') |
| private automaticReviewInput?: HTMLInputElement; |
| |
| @query('#syntaxHighlightInput') |
| private syntaxHighlightInput?: HTMLInputElement; |
| |
| @query('#ignoreWhiteSpace') private ignoreWhiteSpace?: HTMLInputElement; |
| |
| // Used in gr-diff-preferences-dialog |
| @query('#contextSelect') contextSelect?: GrSelect; |
| |
| @state() diffPrefs?: DiffPreferencesInfo; |
| |
| @state() private originalDiffPrefs?: DiffPreferencesInfo; |
| |
| private readonly userModel = getAppContext().userModel; |
| |
| constructor() { |
| super(); |
| subscribe( |
| this, |
| () => this.userModel.diffPreferences$, |
| diffPreferences => { |
| if (!diffPreferences) return; |
| this.originalDiffPrefs = diffPreferences; |
| this.diffPrefs = {...diffPreferences}; |
| } |
| ); |
| } |
| |
| static override get styles() { |
| return [sharedStyles, formStyles]; |
| } |
| |
| override render() { |
| return html` |
| <div id="diffPreferences" class="gr-form-styles"> |
| <section> |
| <label for="contextLineSelect" class="title">Context</label> |
| <span class="value"> |
| <gr-select |
| id="contextSelect" |
| .bindValue=${convertToString(this.diffPrefs?.context)} |
| @change=${this.handleDiffContextChanged} |
| > |
| <select id="contextLineSelect"> |
| <option value="3">3 lines</option> |
| <option value="10">10 lines</option> |
| <option value="25">25 lines</option> |
| <option value="50">50 lines</option> |
| <option value="75">75 lines</option> |
| <option value="100">100 lines</option> |
| <option value="-1">Whole file</option> |
| </select> |
| </gr-select> |
| </span> |
| </section> |
| <section> |
| <label for="lineWrappingInput" class="title">Fit to screen</label> |
| <span class="value"> |
| <input |
| id="lineWrappingInput" |
| type="checkbox" |
| ?checked=${this.diffPrefs?.line_wrapping} |
| @change=${this.handleLineWrappingTap} |
| /> |
| </span> |
| </section> |
| <section> |
| <label for="columnsInput" class="title">Diff width</label> |
| <span class="value"> |
| <iron-input |
| .allowedPattern=${'[0-9]'} |
| .bindValue=${convertToString(this.diffPrefs?.line_length)} |
| @change=${this.handleDiffLineLengthChanged} |
| > |
| <input id="columnsInput" type="number" /> |
| </iron-input> |
| </span> |
| </section> |
| <section> |
| <label for="tabSizeInput" class="title">Tab width</label> |
| <span class="value"> |
| <iron-input |
| .allowedPattern=${'[0-9]'} |
| .bindValue=${convertToString(this.diffPrefs?.tab_size)} |
| @change=${this.handleDiffTabSizeChanged} |
| > |
| <input id="tabSizeInput" type="number" /> |
| </iron-input> |
| </span> |
| </section> |
| <section> |
| <label for="fontSizeInput" class="title">Font size</label> |
| <span class="value"> |
| <iron-input |
| .allowedPattern=${'[0-9]'} |
| .bindValue=${convertToString(this.diffPrefs?.font_size)} |
| @change=${this.handleDiffFontSizeChanged} |
| > |
| <input id="fontSizeInput" type="number" /> |
| </iron-input> |
| </span> |
| </section> |
| <section> |
| <label for="showTabsInput" class="title">Show tabs</label> |
| <span class="value"> |
| <input |
| id="showTabsInput" |
| type="checkbox" |
| ?checked=${this.diffPrefs?.show_tabs} |
| @change=${this.handleShowTabsTap} |
| /> |
| </span> |
| </section> |
| <section> |
| <label for="showTrailingWhitespaceInput" class="title" |
| >Show trailing whitespace</label |
| > |
| <span class="value"> |
| <input |
| id="showTrailingWhitespaceInput" |
| type="checkbox" |
| ?checked=${this.diffPrefs?.show_whitespace_errors} |
| @change=${this.handleShowTrailingWhitespaceTap} |
| /> |
| </span> |
| </section> |
| <section> |
| <label for="syntaxHighlightInput" class="title" |
| >Syntax highlighting</label |
| > |
| <span class="value"> |
| <input |
| id="syntaxHighlightInput" |
| type="checkbox" |
| ?checked=${this.diffPrefs?.syntax_highlighting} |
| @change=${this.handleSyntaxHighlightTap} |
| /> |
| </span> |
| </section> |
| <section> |
| <label for="automaticReviewInput" class="title" |
| >Automatically mark viewed files reviewed</label |
| > |
| <span class="value"> |
| <input |
| id="automaticReviewInput" |
| type="checkbox" |
| ?checked=${!this.diffPrefs?.manual_review} |
| @change=${this.handleAutomaticReviewTap} |
| /> |
| </span> |
| </section> |
| <section> |
| <div class="pref"> |
| <label for="ignoreWhiteSpace" class="title" |
| >Ignore Whitespace</label |
| > |
| <span class="value"> |
| <gr-select |
| .bindValue=${convertToString(this.diffPrefs?.ignore_whitespace)} |
| @change=${this.handleDiffIgnoreWhitespaceChanged} |
| > |
| <select id="ignoreWhiteSpace"> |
| <option value="IGNORE_NONE">None</option> |
| <option value="IGNORE_TRAILING">Trailing</option> |
| <option value="IGNORE_LEADING_AND_TRAILING"> |
| Leading & trailing |
| </option> |
| <option value="IGNORE_ALL">All</option> |
| </select> |
| </gr-select> |
| </span> |
| </div> |
| </section> |
| </div> |
| `; |
| } |
| |
| private readonly handleDiffContextChanged = () => { |
| this.diffPrefs!.context = Number(this.contextLineSelect!.value); |
| fire(this, 'has-unsaved-changes-changed', { |
| value: this.hasUnsavedChanges(), |
| }); |
| }; |
| |
| private readonly handleLineWrappingTap = () => { |
| this.diffPrefs!.line_wrapping = this.lineWrappingInput!.checked; |
| fire(this, 'has-unsaved-changes-changed', { |
| value: this.hasUnsavedChanges(), |
| }); |
| }; |
| |
| private readonly handleDiffLineLengthChanged = () => { |
| this.diffPrefs!.line_length = Number(this.columnsInput!.value); |
| fire(this, 'has-unsaved-changes-changed', { |
| value: this.hasUnsavedChanges(), |
| }); |
| }; |
| |
| private readonly handleDiffTabSizeChanged = () => { |
| this.diffPrefs!.tab_size = Number(this.tabSizeInput!.value); |
| fire(this, 'has-unsaved-changes-changed', { |
| value: this.hasUnsavedChanges(), |
| }); |
| }; |
| |
| private readonly handleDiffFontSizeChanged = () => { |
| this.diffPrefs!.font_size = Number(this.fontSizeInput!.value); |
| fire(this, 'has-unsaved-changes-changed', { |
| value: this.hasUnsavedChanges(), |
| }); |
| }; |
| |
| private readonly handleShowTabsTap = () => { |
| this.diffPrefs!.show_tabs = this.showTabsInput!.checked; |
| fire(this, 'has-unsaved-changes-changed', { |
| value: this.hasUnsavedChanges(), |
| }); |
| }; |
| |
| // private but used in test |
| readonly handleShowTrailingWhitespaceTap = () => { |
| this.diffPrefs!.show_whitespace_errors = |
| this.showTrailingWhitespaceInput!.checked; |
| fire(this, 'has-unsaved-changes-changed', { |
| value: this.hasUnsavedChanges(), |
| }); |
| }; |
| |
| private readonly handleSyntaxHighlightTap = () => { |
| this.diffPrefs!.syntax_highlighting = this.syntaxHighlightInput!.checked; |
| fire(this, 'has-unsaved-changes-changed', { |
| value: this.hasUnsavedChanges(), |
| }); |
| }; |
| |
| private readonly handleAutomaticReviewTap = () => { |
| this.diffPrefs!.manual_review = !this.automaticReviewInput!.checked; |
| fire(this, 'has-unsaved-changes-changed', { |
| value: this.hasUnsavedChanges(), |
| }); |
| }; |
| |
| private readonly handleDiffIgnoreWhitespaceChanged = () => { |
| this.diffPrefs!.ignore_whitespace = this.ignoreWhiteSpace! |
| .value as IgnoreWhitespaceType; |
| fire(this, 'has-unsaved-changes-changed', { |
| value: this.hasUnsavedChanges(), |
| }); |
| }; |
| |
| hasUnsavedChanges() { |
| // We have to wrap boolean values in Boolean() to ensure undefined values |
| // use false rather than undefined. |
| return ( |
| this.originalDiffPrefs?.context !== this.diffPrefs?.context || |
| Boolean(this.originalDiffPrefs?.line_wrapping) !== |
| Boolean(this.diffPrefs?.line_wrapping) || |
| this.originalDiffPrefs?.line_length !== this.diffPrefs?.line_length || |
| this.originalDiffPrefs?.tab_size !== this.diffPrefs?.tab_size || |
| this.originalDiffPrefs?.font_size !== this.diffPrefs?.font_size || |
| this.originalDiffPrefs?.ignore_whitespace !== |
| this.diffPrefs?.ignore_whitespace || |
| Boolean(this.originalDiffPrefs?.show_tabs) !== |
| Boolean(this.diffPrefs?.show_tabs) || |
| Boolean(this.originalDiffPrefs?.show_whitespace_errors) !== |
| Boolean(this.diffPrefs?.show_whitespace_errors) || |
| Boolean(this.originalDiffPrefs?.manual_review) !== |
| Boolean(this.diffPrefs?.manual_review) |
| ); |
| } |
| |
| async save() { |
| if (!this.diffPrefs) return; |
| await this.userModel.updateDiffPreference(this.diffPrefs); |
| fire(this, 'has-unsaved-changes-changed', { |
| value: this.hasUnsavedChanges(), |
| }); |
| } |
| } |
| |
| declare global { |
| interface HTMLElementEventMap { |
| 'has-unsaved-changes-changed': ValueChangedEvent<boolean>; |
| } |
| interface HTMLElementTagNameMap { |
| 'gr-diff-preferences': GrDiffPreferences; |
| } |
| } |