Show vsyncs as a colored dividor instead of a full entry in transactionsView

Test: Visual
Change-Id: I1b7d384bf9cca3fe89878b835a1ba7002d732ef7
diff --git a/tools/winscope/src/TransactionEntry.vue b/tools/winscope/src/TransactionEntry.vue
index fb0702b..42fef31 100644
--- a/tools/winscope/src/TransactionEntry.vue
+++ b/tools/winscope/src/TransactionEntry.vue
@@ -1,46 +1,60 @@
 <template>
-  <div class="entry"
-    :class="{
-      inactive: source.timestamp > currentTimestamp,
-      selected: isSelected
-    }"
-    @click="onClick(source)"
-  >
-    <div class="time-column">
-      <a @click="setTimelineTime(source.timestamp)" class="time-link">
-        {{source.time}}
-      </a>
-      <div
-        class="new-badge"
-        :style="{visibility: source.new ? 'visible' : 'hidden'} "
-      >
-        New
+  <div>
+
+    <div v-if="source.type === 'vsyncEvent'" class="vsync">
+      <div class="vsync-dot" />
+      <md-tooltip md-direction="left">
+        VSync
+      </md-tooltip>
+    </div>
+
+    <div v-else
+      class="entry"
+      :class="{
+        inactive: source.timestamp > currentTimestamp,
+        selected: isSelected
+      }"
+      @click="onClick(source)"
+    >
+      <div class="time-column">
+        <a @click="setTimelineTime(source.timestamp)" class="time-link">
+          {{source.time}}
+        </a>
+        <div
+          class="new-badge"
+          :style="{visibility: source.new ? 'visible' : 'hidden'} "
+        >
+          New
+        </div>
+      </div>
+      <div class="type-column">{{transactionTypeOf(source)}}</div>
+      <div class="affected-surfaces-column">
+        <span
+          v-for="(surface, index) in sufacesAffectedBy(source)"
+          v-bind:key="surface.id"
+        >
+          <!-- eslint-disable-next-line max-len -->
+          <span v-if="surface.name" class="surface-name">{{ surface.name }}</span>
+          <span class="surface-id">
+            <!-- eslint-disable-next-line max-len -->
+            <span v-if="surface.name">(</span>{{surface.id}}<span v-if="surface.name">)</span>
+          </span>
+          <!-- eslint-disable-next-line max-len -->
+          <span v-if="index + 1 < sufacesAffectedBy(source).length">,&nbsp;</span>
+        </span>
+      </div>
+      <div class="extra-info-column">
+        <span v-if="source.identifier">
+          <!-- eslint-disable-next-line max-len -->
+          Tx Id: <span class="light">{{ prettifyTransactionId(source.identifier) }}</span><br/>
+        </span>
+        <span v-if="source.origin">
+          PID: <span class="light">{{ source.origin.pid }}</span><br/>
+          TID: <span class="light">{{ source.origin.uid }}</span><br/>
+        </span>
       </div>
     </div>
-    <div class="type-column">{{transactionTypeOf(source)}}</div>
-    <div class="affected-surfaces-column">
-      <span
-        v-for="(surface, index) in sufacesAffectedBy(source)"
-        v-bind:key="surface.id"
-      >
-        <span v-if="surface.name" class="surface-name">{{ surface.name }}</span>
-        <span class="surface-id">
-          <!-- eslint-disable-next-line max-len -->
-          <span v-if="surface.name">(</span>{{surface.id}}<span v-if="surface.name">)</span>
-        </span>
-        <span v-if="index + 1 < sufacesAffectedBy(source).length">,&nbsp;</span>
-      </span>
-    </div>
-    <div class="extra-info-column">
-      <span v-if="source.identifier">
-        <!-- eslint-disable-next-line max-len -->
-        Tx Id: <span class="light">{{ prettifyTransactionId(source.identifier) }}</span><br/>
-      </span>
-      <span v-if="source.origin">
-        PID: <span class="light">{{ source.origin.pid }}</span><br/>
-        TID: <span class="light">{{ source.origin.uid }}</span><br/>
-      </span>
-    </div>
+
   </div>
 </template>
 
@@ -170,6 +184,11 @@
   cursor: pointer;
 }
 
+.entry > div {
+  padding: 6px 10px;
+  border-bottom: 1px solid #f1f1f1;
+}
+
 .entry.selected {
   background-color: #365179;
   color: white;
@@ -183,11 +202,6 @@
   background: #f1f1f1;
 }
 
-.entry > div {
-  padding: 6px 10px;
-  border-bottom: 1px solid #f1f1f1;
-}
-
 a {
   cursor: pointer;
 }
@@ -225,4 +239,31 @@
 .inactive .light {
   color: #b4b4b4
 }
+
+.vsync {
+  position: relative;
+}
+
+.vsync-dot:before {
+  content: "";
+  position: absolute;
+  left: 0;
+  top: -5px;
+  height: 10px;
+  width: 10px;
+  background-color: rgb(170, 65, 255);
+  border-radius: 50%;
+  display: inline-block;
+}
+
+.vsync-dot:after {
+  content: "";
+  position: absolute;
+  left: 0;
+  top: 0;
+  height: 1px;
+  width: 100%;
+  background-color: rgb(170, 65, 255);
+  display: inline-block;
+}
 </style>
diff --git a/tools/winscope/src/TransactionsView.vue b/tools/winscope/src/TransactionsView.vue
index 66002a3..7af009b 100644
--- a/tools/winscope/src/TransactionsView.vue
+++ b/tools/winscope/src/TransactionsView.vue
@@ -169,6 +169,10 @@
       }
     }
 
+    // Remove vsync from being transaction types that can be filtered
+    // We want to always show vsyncs
+    transactionTypes.delete('vsyncEvent');
+
     return {
       transactionTypes: Array.from(transactionTypes),
       properties: Array.from(properties),
@@ -197,6 +201,7 @@
       if (this.selectedTransactionTypes.length > 0) {
         filteredData = filteredData.filter(
             this.filterTransactions((transaction) =>
+              transaction.type === 'vsyncEvent' ||
               this.selectedTransactionTypes.includes(transaction.type)));
       }
 
@@ -247,7 +252,10 @@
         );
       }
 
-      return filteredData;
+      // We quish vsyncs because otherwise the lazy list will not load enough
+      // elements if there are many vsyncs in a row since vsyncs take up no
+      // space.
+      return this.squishVSyncs(filteredData);
     },
 
   },
@@ -435,6 +443,14 @@
       const expandedId = expandTransactionId(transactionId);
       return `${expandedId.pid}.${expandedId.id}`;
     },
+
+    squishVSyncs(data) {
+      return data.filter((event, i) => {
+        console.log(event.type, data[i + 1]?.type);
+        return !(event.type === 'vsyncEvent' &&
+          data[i + 1]?.type === 'vsyncEvent');
+      });
+    },
   },
   components: {
     'virtual-list': VirtualList,
@@ -501,4 +517,8 @@
 .no-properties span {
   font-weight: 100;
 }
+
+.transaction-event {
+  display: inline-flex;
+}
 </style>