|  | /** | 
|  | * @license | 
|  | * Copyright (C) 2020 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 {html} from '@polymer/polymer/lib/utils/html-tag.js'; | 
|  |  | 
|  | export const htmlTemplate = html` | 
|  | <style include="shared-styles"> | 
|  | :host { | 
|  | display: block; | 
|  | } | 
|  | .row { | 
|  | align-items: center; | 
|  | border-top: 1px solid var(--border-color); | 
|  | display: flex; | 
|  | min-height: calc(var(--line-height-normal) + 2 * var(--spacing-s)); | 
|  | padding: var(--spacing-xs) var(--spacing-l) var(--spacing-xs) | 
|  | calc(var(--spacing-l) - 0.35rem); | 
|  | } | 
|  | :host(.loading) .row { | 
|  | opacity: 0.5; | 
|  | } | 
|  | :host(.editMode) .hideOnEdit { | 
|  | display: none; | 
|  | } | 
|  | .showOnEdit { | 
|  | display: none; | 
|  | } | 
|  | :host(.editMode) .showOnEdit { | 
|  | display: initial; | 
|  | } | 
|  | .invisible { | 
|  | visibility: hidden; | 
|  | } | 
|  | .header-row { | 
|  | background-color: var(--background-color-secondary); | 
|  | } | 
|  | .controlRow { | 
|  | align-items: center; | 
|  | display: flex; | 
|  | height: 2.25em; | 
|  | justify-content: center; | 
|  | } | 
|  | .controlRow.invisible, | 
|  | .show-hide.invisible { | 
|  | display: none; | 
|  | } | 
|  | .reviewed, | 
|  | .status { | 
|  | align-items: center; | 
|  | display: inline-flex; | 
|  | } | 
|  | .reviewed, | 
|  | .status { | 
|  | display: inline-block; | 
|  | text-align: left; | 
|  | width: 1.5em; | 
|  | } | 
|  | .file-row { | 
|  | cursor: pointer; | 
|  | } | 
|  | .file-row.expanded { | 
|  | border-bottom: 1px solid var(--border-color); | 
|  | position: -webkit-sticky; | 
|  | position: sticky; | 
|  | top: 0; | 
|  | /* Has to visible above the diff view, and by default has a lower | 
|  | z-index. setting to 1 places it directly above. */ | 
|  | z-index: 1; | 
|  | } | 
|  | .file-row:hover { | 
|  | background-color: var(--hover-background-color); | 
|  | } | 
|  | .file-row.selected { | 
|  | background-color: var(--selection-background-color); | 
|  | } | 
|  | .file-row.expanded, | 
|  | .file-row.expanded:hover { | 
|  | background-color: var(--expanded-background-color); | 
|  | } | 
|  | .path { | 
|  | cursor: pointer; | 
|  | flex: 1; | 
|  | /* Wrap it into multiple lines if too long. */ | 
|  | white-space: normal; | 
|  | word-break: break-word; | 
|  | } | 
|  | .oldPath { | 
|  | color: var(--deemphasized-text-color); | 
|  | } | 
|  | .header-stats { | 
|  | text-align: center; | 
|  | min-width: 7.5em; | 
|  | } | 
|  | .stats { | 
|  | text-align: right; | 
|  | min-width: 7.5em; | 
|  | } | 
|  | .comments { | 
|  | padding-left: var(--spacing-l); | 
|  | min-width: 7.5em; | 
|  | } | 
|  | .row:not(.header-row) .stats, | 
|  | .total-stats { | 
|  | font-family: var(--monospace-font-family); | 
|  | font-size: var(--font-size-mono); | 
|  | line-height: var(--line-height-mono); | 
|  | display: flex; | 
|  | } | 
|  | .sizeBars { | 
|  | margin-left: var(--spacing-m); | 
|  | min-width: 7em; | 
|  | text-align: center; | 
|  | } | 
|  | .sizeBars.hide { | 
|  | display: none; | 
|  | } | 
|  | .added, | 
|  | .removed { | 
|  | display: inline-block; | 
|  | min-width: 3.5em; | 
|  | } | 
|  | .added { | 
|  | color: var(--vote-text-color-recommended); | 
|  | } | 
|  | .removed { | 
|  | color: var(--vote-text-color-disliked); | 
|  | text-align: left; | 
|  | min-width: 4em; | 
|  | padding-left: var(--spacing-s); | 
|  | } | 
|  | .drafts { | 
|  | color: #c62828; | 
|  | font-weight: var(--font-weight-bold); | 
|  | } | 
|  | .show-hide { | 
|  | margin-left: var(--spacing-s); | 
|  | width: 1.9em; | 
|  | } | 
|  | .fileListButton { | 
|  | margin: var(--spacing-m); | 
|  | } | 
|  | .totalChanges { | 
|  | justify-content: flex-end; | 
|  | text-align: right; | 
|  | } | 
|  | .warning { | 
|  | color: var(--deemphasized-text-color); | 
|  | } | 
|  | input.show-hide { | 
|  | display: none; | 
|  | } | 
|  | label.show-hide { | 
|  | cursor: pointer; | 
|  | display: block; | 
|  | min-width: 2em; | 
|  | } | 
|  | gr-diff { | 
|  | display: block; | 
|  | overflow-x: auto; | 
|  | } | 
|  | .truncatedFileName { | 
|  | display: none; | 
|  | } | 
|  | .mobile { | 
|  | display: none; | 
|  | } | 
|  | .reviewed { | 
|  | margin-left: var(--spacing-xxl); | 
|  | width: 15em; | 
|  | } | 
|  | .reviewed label { | 
|  | color: var(--link-color); | 
|  | opacity: 0; | 
|  | justify-content: flex-end; | 
|  | width: 100%; | 
|  | } | 
|  | .reviewed label:hover { | 
|  | cursor: pointer; | 
|  | opacity: 100; | 
|  | } | 
|  | .row:focus { | 
|  | outline: none; | 
|  | } | 
|  | .row:hover .reviewed label, | 
|  | .row:focus .reviewed label, | 
|  | .row.expanded .reviewed label { | 
|  | opacity: 100; | 
|  | } | 
|  | .reviewed input { | 
|  | display: none; | 
|  | } | 
|  | .reviewedLabel { | 
|  | color: var(--deemphasized-text-color); | 
|  | margin-right: var(--spacing-l); | 
|  | opacity: 0; | 
|  | } | 
|  | .reviewedLabel.isReviewed { | 
|  | display: initial; | 
|  | opacity: 100; | 
|  | } | 
|  | .editFileControls { | 
|  | width: 7em; | 
|  | } | 
|  | .markReviewed, | 
|  | .pathLink { | 
|  | display: inline-block; | 
|  | margin: -2px 0; | 
|  | padding: var(--spacing-s) 0; | 
|  | text-decoration: none; | 
|  | } | 
|  | .pathLink:hover { | 
|  | text-decoration: underline; | 
|  | } | 
|  |  | 
|  | /** copy on file path **/ | 
|  | .pathLink gr-copy-clipboard, | 
|  | .oldPath gr-copy-clipboard { | 
|  | display: inline-block; | 
|  | visibility: hidden; | 
|  | vertical-align: bottom; | 
|  | text-decoration: none; | 
|  | --gr-button: { | 
|  | padding: 0px; | 
|  | } | 
|  | } | 
|  | .pathLink:hover gr-copy-clipboard, | 
|  | .oldPath:hover gr-copy-clipboard { | 
|  | visibility: visible; | 
|  | } | 
|  |  | 
|  | /** small screen breakpoint: 768px */ | 
|  | @media screen and (max-width: 55em) { | 
|  | .desktop { | 
|  | display: none; | 
|  | } | 
|  | .mobile { | 
|  | display: block; | 
|  | } | 
|  | .row.selected { | 
|  | background-color: var(--view-background-color); | 
|  | } | 
|  | .stats { | 
|  | display: none; | 
|  | } | 
|  | .reviewed, | 
|  | .status { | 
|  | justify-content: flex-start; | 
|  | } | 
|  | .reviewed { | 
|  | display: none; | 
|  | } | 
|  | .comments { | 
|  | min-width: initial; | 
|  | } | 
|  | .expanded .fullFileName, | 
|  | .truncatedFileName { | 
|  | display: inline; | 
|  | } | 
|  | .expanded .truncatedFileName, | 
|  | .fullFileName { | 
|  | display: none; | 
|  | } | 
|  | } | 
|  | </style> | 
|  | <div id="container" on-click="_handleFileListClick"> | 
|  | <div class="header-row row"> | 
|  | <div class="status"></div> | 
|  | <div class="path">File</div> | 
|  | <div class="comments">Comments</div> | 
|  | <div class="sizeBars">Size</div> | 
|  | <div class="header-stats">Delta</div> | 
|  | <template is="dom-if" if="[[_showDynamicColumns]]"> | 
|  | <template | 
|  | is="dom-repeat" | 
|  | items="[[_dynamicHeaderEndpoints]]" | 
|  | as="headerEndpoint" | 
|  | > | 
|  | <gr-endpoint-decorator name$="[[headerEndpoint]]"> | 
|  | </gr-endpoint-decorator> | 
|  | </template> | 
|  | </template> | 
|  | <!-- Empty div here exists to keep spacing in sync with file rows. --> | 
|  | <div class="reviewed hideOnEdit" hidden$="[[!_loggedIn]]"></div> | 
|  | <div class="editFileControls showOnEdit"></div> | 
|  | <div class="show-hide"></div> | 
|  | </div> | 
|  |  | 
|  | <template | 
|  | is="dom-repeat" | 
|  | items="[[_shownFiles]]" | 
|  | id="files" | 
|  | as="file" | 
|  | initial-count="[[fileListIncrement]]" | 
|  | target-framerate="1" | 
|  | > | 
|  | [[_reportRenderedRow(index)]] | 
|  | <div class="stickyArea"> | 
|  | <div | 
|  | class$="file-row row [[_computePathClass(file.__path, _expandedFiles.*)]]" | 
|  | data-file$="[[_computeFileData(file)]]" | 
|  | tabindex="-1" | 
|  | > | 
|  | <div | 
|  | class$="[[_computeClass('status', file.__path)]]" | 
|  | tabindex="0" | 
|  | title$="[[_computeFileStatusLabel(file.status)]]" | 
|  | aria-label$="[[_computeFileStatusLabel(file.status)]]" | 
|  | > | 
|  | [[_computeFileStatus(file.status)]] | 
|  | </div> | 
|  | <!-- TODO: Remove data-url as it appears its not used --> | 
|  | <span | 
|  | data-url="[[_computeDiffURL(change, patchRange, file.__path, editMode)]]" | 
|  | class="path" | 
|  | > | 
|  | <a | 
|  | class="pathLink" | 
|  | href$="[[_computeDiffURL(change, patchRange, file.__path, editMode)]]" | 
|  | > | 
|  | <span | 
|  | title$="[[computeDisplayPath(file.__path)]]" | 
|  | class="fullFileName" | 
|  | > | 
|  | [[computeDisplayPath(file.__path)]] | 
|  | </span> | 
|  | <span | 
|  | title$="[[computeDisplayPath(file.__path)]]" | 
|  | class="truncatedFileName" | 
|  | > | 
|  | [[computeTruncatedPath(file.__path)]] | 
|  | </span> | 
|  | <gr-copy-clipboard | 
|  | hide-input="" | 
|  | text="[[file.__path]]" | 
|  | ></gr-copy-clipboard> | 
|  | </a> | 
|  | <template is="dom-if" if="[[file.old_path]]"> | 
|  | <div class="oldPath" title$="[[file.old_path]]"> | 
|  | [[file.old_path]] | 
|  | <gr-copy-clipboard | 
|  | hide-input="" | 
|  | text="[[file.old_path]]" | 
|  | ></gr-copy-clipboard> | 
|  | </div> | 
|  | </template> | 
|  | </span> | 
|  | <div class="comments desktop"> | 
|  | <span class="drafts"> | 
|  | [[_computeDraftsString(changeComments, patchRange, file.__path)]] | 
|  | </span> | 
|  | [[_computeCommentsString(changeComments, patchRange, file.__path)]] | 
|  | </div> | 
|  | <div class="comments mobile"> | 
|  | <span class="drafts"> | 
|  | [[_computeDraftsStringMobile(changeComments, patchRange, | 
|  | file.__path)]] | 
|  | </span> | 
|  | [[_computeCommentsStringMobile(changeComments, patchRange, | 
|  | file.__path)]] | 
|  | </div> | 
|  | <div class$="[[_computeSizeBarsClass(_showSizeBars, file.__path)]]"> | 
|  | <svg width="61" height="8"> | 
|  | <rect | 
|  | x$="[[_computeBarAdditionX(file, _sizeBarLayout)]]" | 
|  | y="0" | 
|  | height="8" | 
|  | fill="#388E3C" | 
|  | width$="[[_computeBarAdditionWidth(file, _sizeBarLayout)]]" | 
|  | ></rect> | 
|  | <rect | 
|  | x$="[[_computeBarDeletionX(_sizeBarLayout)]]" | 
|  | y="0" | 
|  | height="8" | 
|  | fill="#D32F2F" | 
|  | width$="[[_computeBarDeletionWidth(file, _sizeBarLayout)]]" | 
|  | ></rect> | 
|  | </svg> | 
|  | </div> | 
|  | <div class$="[[_computeClass('stats', file.__path)]]"> | 
|  | <span | 
|  | class="added" | 
|  | tabindex="0" | 
|  | aria-label$="[[file.lines_inserted]] lines added" | 
|  | hidden$="[[file.binary]]" | 
|  | > | 
|  | +[[file.lines_inserted]] | 
|  | </span> | 
|  | <span | 
|  | class="removed" | 
|  | tabindex="0" | 
|  | aria-label$="[[file.lines_deleted]] lines removed" | 
|  | hidden$="[[file.binary]]" | 
|  | > | 
|  | -[[file.lines_deleted]] | 
|  | </span> | 
|  | <span | 
|  | class$="[[_computeBinaryClass(file.size_delta)]]" | 
|  | hidden$="[[!file.binary]]" | 
|  | > | 
|  | [[_formatBytes(file.size_delta)]] [[_formatPercentage(file.size, | 
|  | file.size_delta)]] | 
|  | </span> | 
|  | </div> | 
|  | <template is="dom-if" if="[[_showDynamicColumns]]"> | 
|  | <template | 
|  | is="dom-repeat" | 
|  | items="[[_dynamicContentEndpoints]]" | 
|  | as="contentEndpoint" | 
|  | > | 
|  | <div class$="[[_computeClass('', file.__path)]]"> | 
|  | <gr-endpoint-decorator name="[[contentEndpoint]]"> | 
|  | <gr-endpoint-param name="changeNum" value="[[changeNum]]"> | 
|  | </gr-endpoint-param> | 
|  | <gr-endpoint-param name="patchRange" value="[[patchRange]]"> | 
|  | </gr-endpoint-param> | 
|  | <gr-endpoint-param name="path" value="[[file.__path]]"> | 
|  | </gr-endpoint-param> | 
|  | </gr-endpoint-decorator> | 
|  | </div> | 
|  | </template> | 
|  | </template> | 
|  | <div class="reviewed hideOnEdit" hidden$="[[!_loggedIn]]" hidden=""> | 
|  | <span | 
|  | class$="reviewedLabel [[_computeReviewedClass(file.isReviewed)]]" | 
|  | >Reviewed</span | 
|  | > | 
|  | <label> | 
|  | <input | 
|  | class="reviewed" | 
|  | type="checkbox" | 
|  | checked="[[file.isReviewed]]" | 
|  | /> | 
|  | <span | 
|  | class="markReviewed" | 
|  | title$="[[_reviewedTitle(file.isReviewed)]]" | 
|  | >[[_computeReviewedText(file.isReviewed)]]</span | 
|  | > | 
|  | </label> | 
|  | </div> | 
|  | <div class="editFileControls showOnEdit"> | 
|  | <template is="dom-if" if="[[editMode]]"> | 
|  | <gr-edit-file-controls | 
|  | class$="[[_computeClass('', file.__path)]]" | 
|  | file-path="[[file.__path]]" | 
|  | ></gr-edit-file-controls> | 
|  | </template> | 
|  | </div> | 
|  | <div class="show-hide"> | 
|  | <label | 
|  | class="show-hide" | 
|  | data-path$="[[file.__path]]" | 
|  | data-expand="true" | 
|  | > | 
|  | <input | 
|  | type="checkbox" | 
|  | class="show-hide" | 
|  | checked$="[[_isFileExpanded(file.__path, _expandedFiles.*)]]" | 
|  | data-path$="[[file.__path]]" | 
|  | data-expand="true" | 
|  | /> | 
|  | <iron-icon | 
|  | id="icon" | 
|  | icon="[[_computeShowHideIcon(file.__path, _expandedFiles.*)]]" | 
|  | > | 
|  | </iron-icon> | 
|  | </label> | 
|  | </div> | 
|  | </div> | 
|  | <template | 
|  | is="dom-if" | 
|  | if="[[_isFileExpanded(file.__path, _expandedFiles.*)]]" | 
|  | > | 
|  | <gr-diff-host | 
|  | no-auto-render="" | 
|  | show-load-failure="" | 
|  | display-line="[[_displayLine]]" | 
|  | hidden="[[!_isFileExpanded(file.__path, _expandedFiles.*)]]" | 
|  | change-num="[[changeNum]]" | 
|  | patch-range="[[patchRange]]" | 
|  | path="[[file.__path]]" | 
|  | prefs="[[diffPrefs]]" | 
|  | project-name="[[change.project]]" | 
|  | no-render-on-prefs-change="" | 
|  | view-mode="[[diffViewMode]]" | 
|  | ></gr-diff-host> | 
|  | </template> | 
|  | </div> | 
|  | </template> | 
|  | </div> | 
|  | <div class="row totalChanges" hidden$="[[_hideChangeTotals]]"> | 
|  | <div class="total-stats"> | 
|  | <span | 
|  | class="added" | 
|  | tabindex="0" | 
|  | aria-label$="[[_patchChange.inserted]] lines added" | 
|  | > | 
|  | +[[_patchChange.inserted]] | 
|  | </span> | 
|  | <span | 
|  | class="removed" | 
|  | tabindex="0" | 
|  | aria-label$="[[_patchChange.deleted]] lines removed" | 
|  | > | 
|  | -[[_patchChange.deleted]] | 
|  | </span> | 
|  | </div> | 
|  | <template is="dom-if" if="[[_showDynamicColumns]]"> | 
|  | <template | 
|  | is="dom-repeat" | 
|  | items="[[_dynamicSummaryEndpoints]]" | 
|  | as="summaryEndpoint" | 
|  | > | 
|  | <gr-endpoint-decorator name="[[summaryEndpoint]]"> | 
|  | </gr-endpoint-decorator> | 
|  | </template> | 
|  | </template> | 
|  | <!-- Empty div here exists to keep spacing in sync with file rows. --> | 
|  | <div class="reviewed hideOnEdit" hidden$="[[!_loggedIn]]"></div> | 
|  | <div class="editFileControls showOnEdit"></div> | 
|  | <div class="show-hide"></div> | 
|  | </div> | 
|  | <div class="row totalChanges" hidden$="[[_hideBinaryChangeTotals]]"> | 
|  | <div class="total-stats"> | 
|  | <span class="added" aria-label="Total lines added"> | 
|  | [[_formatBytes(_patchChange.size_delta_inserted)]] | 
|  | [[_formatPercentage(_patchChange.total_size, | 
|  | _patchChange.size_delta_inserted)]] | 
|  | </span> | 
|  | <span class="removed" aria-label="Total lines removed"> | 
|  | [[_formatBytes(_patchChange.size_delta_deleted)]] | 
|  | [[_formatPercentage(_patchChange.total_size, | 
|  | _patchChange.size_delta_deleted)]] | 
|  | </span> | 
|  | </div> | 
|  | </div> | 
|  | <div | 
|  | class$="row controlRow [[_computeFileListControlClass(numFilesShown, _files)]]" | 
|  | > | 
|  | <gr-button | 
|  | class="fileListButton" | 
|  | id="incrementButton" | 
|  | link="" | 
|  | on-click="_incrementNumFilesShown" | 
|  | > | 
|  | [[_computeIncrementText(numFilesShown, _files)]] | 
|  | </gr-button> | 
|  | <gr-tooltip-content | 
|  | has-tooltip="[[_computeWarnShowAll(_files)]]" | 
|  | show-icon="[[_computeWarnShowAll(_files)]]" | 
|  | title$="[[_computeShowAllWarning(_files)]]" | 
|  | > | 
|  | <gr-button | 
|  | class="fileListButton" | 
|  | id="showAllButton" | 
|  | link="" | 
|  | on-click="_showAllFiles" | 
|  | > | 
|  | [[_computeShowAllText(_files)]] </gr-button | 
|  | ><!-- | 
|  | --></gr-tooltip-content> | 
|  | </div> | 
|  | <gr-diff-preferences-dialog | 
|  | id="diffPreferencesDialog" | 
|  | diff-prefs="{{diffPrefs}}" | 
|  | on-reload-diff-preference="_handleReloadingDiffPreference" | 
|  | > | 
|  | </gr-diff-preferences-dialog> | 
|  | <gr-rest-api-interface id="restAPI"></gr-rest-api-interface> | 
|  | <gr-storage id="storage"></gr-storage> | 
|  | <gr-diff-cursor id="diffCursor"></gr-diff-cursor> | 
|  | <gr-cursor-manager | 
|  | id="fileCursor" | 
|  | scroll-behavior="keep-visible" | 
|  | focus-on-move="" | 
|  | cursor-target-class="selected" | 
|  | ></gr-cursor-manager> | 
|  | <gr-reporting id="reporting"></gr-reporting> | 
|  | `; |