From e93515ef899718884215910088e690eb017543ab Mon Sep 17 00:00:00 2001 From: Priyanka Date: Wed, 11 Aug 2021 14:55:01 +0000 Subject: [PATCH] Add functionality to search + navigate tags/errors. Add a searchbar to bottom of Winscope that can be used to navigate through all the tags/transitions/errors present in a trace (integrating existing timestamp search). Choose the desired tab to set the type of search. Typing input into the relevant search will filter the elements. Click on the start or end timestamp in the scrollable search table to navigate to that timestamp in the timeline. Click on a transition in the search table to navigate to the start timestamp for that transition. Click on a transition in the timeline to toggle between start and end timestamps for that transition. Bug: b/196197875 Test: upload the traces on the bug and test the above implementations on the x20. Change-Id: Ib3a0fff770cc65a38e50a8d99f130752b2f98eeb --- tools/winscope/src/App.vue | 81 ++++- tools/winscope/src/Overlay.vue | 109 ++----- tools/winscope/src/Searchbar.vue | 308 ++++++++++++++++++ tools/winscope/src/Timeline.vue | 11 +- .../TagDisplay/TransitionContainer.vue | 26 +- tools/winscope/src/mixins/Timeline.js | 26 +- tools/winscope/src/utils/consts.js | 20 +- 7 files changed, 470 insertions(+), 111 deletions(-) create mode 100644 tools/winscope/src/Searchbar.vue diff --git a/tools/winscope/src/App.vue b/tools/winscope/src/App.vue index 6c8bc2c4a..291ae7a4a 100644 --- a/tools/winscope/src/App.vue +++ b/tools/winscope/src/App.vue @@ -57,8 +57,12 @@ @@ -77,7 +81,8 @@ import FileType from './mixins/FileType.js'; import SaveAsZip from './mixins/SaveAsZip'; import FocusedDataViewFinder from './mixins/FocusedDataViewFinder'; import {DIRECTION} from './utils/utils'; -import {NAVIGATION_STYLE} from './utils/consts'; +import Searchbar from './Searchbar.vue'; +import {NAVIGATION_STYLE, SEARCH_TYPE} from './utils/consts'; const APP_NAME = 'Winscope'; @@ -102,6 +107,10 @@ export default { mainContentStyle: { 'padding-bottom': `${CONTENT_BOTTOM_PADDING}px`, }, + presentTags: [], + presentErrors: [], + searchTypes: [SEARCH_TYPE.TIMESTAMP], + tagAndErrorTraces: false, }; }, created() { @@ -113,7 +122,50 @@ export default { window.removeEventListener('keydown', this.onKeyDown); window.removeEventListener('scroll', this.onScroll); }, + methods: { + /** get states from either tag files or error files */ + getUpdatedStates(files) { + var states = []; + for (const file of files) { + states.push(...file.data); + } + return states; + }, + /** get tags from all uploaded tag files*/ + getUpdatedTags() { + var tagStates = this.getUpdatedStates(this.tagFiles); + var tags = []; + tagStates.forEach(tagState => { + tagState.tags.forEach(tag => { + tag.timestamp = tagState.timestamp; + tags.push(tag); + }); + }); + return tags; + }, + /** get tags from all uploaded error files*/ + getUpdatedErrors() { + var errorStates = this.getUpdatedStates(this.errorFiles); + var errors = []; + //TODO (b/196201487) add check if errors empty + errorStates.forEach(errorState => { + errorState.errors.forEach(error => { + error.timestamp = errorState.timestamp; + errors.push(error); + }); + }); + return errors; + }, + /** set flicker mode check for if there are tag/error traces uploaded*/ + shouldUpdateTagAndErrorTraces() { + return this.tagFiles.length > 0 || this.errorFiles.length > 0; + }, + /** activate flicker search tab if tags/errors uploaded*/ + updateSearchTypes() { + this.searchTypes = [SEARCH_TYPE.TIMESTAMP]; + if (this.tagAndErrorTraces) this.searchTypes.push(SEARCH_TYPE.TAG); + }, clear() { this.$store.commit('clearFiles'); }, @@ -139,6 +191,10 @@ export default { }, onDataReady(files) { this.$store.dispatch('setFiles', files); + this.tagAndErrorTraces = this.shouldUpdateTagAndErrorTraces(); + this.presentTags = this.getUpdatedTags(); + this.presentErrors = this.getUpdatedErrors(); + this.updateSearchTypes(); this.updateFocusedView(); }, setStatus(status) { @@ -176,6 +232,15 @@ export default { dataViewFiles() { return this.files.filter((f) => this.hasDataView(f)); }, + tagFiles() { + return this.$store.getters.tagFiles; + }, + errorFiles() { + return this.$store.getters.errorFiles; + }, + timelineFiles() { + return this.$store.getters.timelineFiles; + }, }, watch: { title() { @@ -187,6 +252,7 @@ export default { dataview: DataView, datainput: DataInput, dataadb: DataAdb, + searchbar: Searchbar, }, }; @@ -194,7 +260,7 @@ export default { @import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@600&display=swap'); #app .md-app-container { - /* Get rid of tranforms which prevent fixed position from being used */ + /* Get rid of transforms which prevent fixed position from being used */ transform: none!important; min-height: 100vh; } @@ -245,15 +311,6 @@ h2 { font-weight: normal; } -ul { - list-style-type: none; - padding: 0; -} - -a { - color: #42b983; -} - .data-inputs { display: flex; flex-wrap: wrap; @@ -293,4 +350,4 @@ a { hyphens: auto; padding: 10px 10px 10px 10px; } - + \ No newline at end of file diff --git a/tools/winscope/src/Overlay.vue b/tools/winscope/src/Overlay.vue index c2c210199..35fbfe70e 100644 --- a/tools/winscope/src/Overlay.vue +++ b/tools/winscope/src/Overlay.vue @@ -52,6 +52,15 @@ > + Show/hide search bar +
- - - - - - Search -
0 || this.errorFiles.length >0; - }, }, updated() { this.$nextTick(() => { @@ -499,34 +494,8 @@ export default { }); }, methods: { - getStates(files) { - var states = []; - for (const file of files) { - states.push(...file.data); - } - return states; - }, - updateTags() { - var tagStates = this.getStates(this.tagFiles); - var tags = []; - tagStates.forEach(tagState => { - const time = this.findClosestTimestamp(tagState.timestamp); - tagState.tags.forEach(tag => { - tag.timestamp = time; - tags.push(tag); - }); - });; - return tags; - }, - updateErrorTimestamps() { - var errorStates = this.getStates(this.errorFiles); - var errorTimestamps = []; - //TODO (b/196201487): update more than one error for each state, add check if errors empty - errorStates.forEach(errorState => { - errorTimestamps.push(errorState.timestamp); - } - ); - return errorTimestamps; + toggleSearch() { + this.search = !(this.search); }, emitBottomHeightUpdate() { if (this.$refs.bottomNav) { @@ -547,9 +516,10 @@ export default { timelines.push(file.timeline); } - while (true) { + var timelineToAdvance = 0; + while (timelineToAdvance !== undefined) { + timelineToAdvance = undefined; let minTime = Infinity; - let timelineToAdvance; for (let i = 0; i < timelines.length; i++) { const timeline = timelines[i]; @@ -715,28 +685,6 @@ export default { clearSelection() { this.crop = null; }, - updateSearchForTimestamp() { - if (/^\d+$/.test(this.searchTimestamp)) { - var roundedTimestamp = parseInt(this.searchTimestamp); - } else { - var roundedTimestamp = string_to_nanos(this.searchTimestamp); - } - var closestTimestamp = this.findClosestTimestamp(roundedTimestamp); - this.$store.dispatch('updateTimelineTime', parseInt(closestTimestamp)); - }, - findClosestTimestamp(roundedTimestamp) { - return this.mergedTimeline.timeline.reduce(function(prev, curr) { - return (Math.abs(curr-roundedTimestamp) < Math.abs(prev-roundedTimestamp) ? curr : prev); - }); - }, - updateTagsAndErrors() { - if (this.tagFiles) { - this.tags = this.updateTags(); - } - if (this.errorFiles) { - this.errorTimestamps = this.updateErrorTimestamps(); - } - }, }, components: { 'timeline': Timeline, @@ -745,6 +693,7 @@ export default { 'videoview': VideoView, 'draggable-div': DraggableDiv, 'md-icon-option': MdIconOption, + 'searchbar': Searchbar, }, }; @@ -948,4 +897,8 @@ export default { margin-bottom: 15px; cursor: help; } + +.drop-search:hover { + background-color: #9af39f; +} diff --git a/tools/winscope/src/Searchbar.vue b/tools/winscope/src/Searchbar.vue new file mode 100644 index 000000000..9178a5873 --- /dev/null +++ b/tools/winscope/src/Searchbar.vue @@ -0,0 +1,308 @@ + + + + \ No newline at end of file diff --git a/tools/winscope/src/Timeline.vue b/tools/winscope/src/Timeline.vue index b9641814d..e5a3ce88e 100644 --- a/tools/winscope/src/Timeline.vue +++ b/tools/winscope/src/Timeline.vue @@ -20,10 +20,13 @@ v-for="transition in timelineTransitions" :key="transition.type" :startPos="transition.startPos" + :startTime="transition.startTime" + :endTime="transition.endTime" :width="transition.width" :color="transition.color" :overlap="transition.overlap" :tooltip="transition.tooltip" + :store="store" />
+ \ No newline at end of file diff --git a/tools/winscope/src/components/TagDisplay/TransitionContainer.vue b/tools/winscope/src/components/TagDisplay/TransitionContainer.vue index 10fa8fff7..701cbad34 100644 --- a/tools/winscope/src/components/TagDisplay/TransitionContainer.vue +++ b/tools/winscope/src/components/TagDisplay/TransitionContainer.vue @@ -13,7 +13,7 @@ limitations under the License. -->
+
{{tooltip}}
@@ -22,6 +22,10 @@