Merge changes Ia70a9794,Iae900bcb

* changes:
  Add ability to specify name for trace
  Add feedback when dragging on the right drop area for file uploads
This commit is contained in:
TreeHugger Robot
2021-11-15 22:15:07 +00:00
committed by Android (Google) Code Review
9 changed files with 208 additions and 30 deletions

View File

@@ -14,9 +14,28 @@
-->
<template>
<div id="app">
<vue-title :appName="appName" :traceName="traceNameForTitle" />
<md-dialog-prompt
class="edit-trace-name-dialog"
:md-active.sync="editingTraceName"
v-model="traceName"
md-title="Edit trace name"
md-input-placeholder="Enter a new trace name"
md-confirm-text="Save" />
<md-app>
<md-app-toolbar md-tag="md-toolbar" class="top-toolbar">
<h1 class="md-title" style="flex: 1">{{title}}</h1>
<h1 class="md-title">{{appName}}</h1>
<div class="trace-name" v-if="dataLoaded">
<div>
<span>{{ traceName }}</span>
<!-- <input type="text" class="trace-name-editable" v-model="traceName" /> -->
<md-icon class="edit-trace-name-btn" @click.native="editTraceName()">edit</md-icon>
</div>
</div>
<md-button
class="md-primary md-theme-default download-all-btn"
@click="generateTags()"
@@ -24,7 +43,7 @@
>Generate Tags</md-button>
<md-button
class="md-primary md-theme-default"
@click="downloadAsZip(files)"
@click="downloadAsZip(files, traceName)"
v-if="dataLoaded"
>Download All</md-button>
<md-button
@@ -39,11 +58,11 @@
<section class="data-inputs" v-if="!dataLoaded">
<div class="input">
<dataadb class="adbinput" ref="adb" :store="store"
@dataReady="onDataReady" @statusChange="setStatus" />
@dataReady="onDataReady" />
</div>
<div class="input" @dragover.prevent @drop.prevent>
<datainput class="fileinput" ref="input" :store="store"
@dataReady="onDataReady" @statusChange="setStatus" />
@dataReady="onDataReady" />
</div>
</section>
@@ -92,6 +111,7 @@ import Searchbar from './Searchbar.vue';
import {NAVIGATION_STYLE, SEARCH_TYPE} from './utils/consts';
import {TRACE_TYPES, FILE_TYPES, dataFile} from './decode.js';
import { TaggingEngine } from './flickerlib/common';
import titleComponent from './Title.vue';
const APP_NAME = 'Winscope';
@@ -102,7 +122,7 @@ export default {
mixins: [FileType, SaveAsZip, FocusedDataViewFinder],
data() {
return {
title: APP_NAME,
appName: APP_NAME,
activeDataView: null,
// eslint-disable-next-line new-cap
store: LocalStore('app', {
@@ -124,12 +144,14 @@ export default {
presentErrors: [],
searchTypes: [SEARCH_TYPE.TIMESTAMP],
hasTagOrErrorTraces: false,
traceName: "unnamed_winscope_trace",
editingTraceName: false
};
},
created() {
window.addEventListener('keydown', this.onKeyDown);
window.addEventListener('scroll', this.onScroll);
document.title = this.title;
// document.title = this.traceName;
},
destroyed() {
window.removeEventListener('keydown', this.onKeyDown);
@@ -226,7 +248,8 @@ export default {
event.preventDefault();
return true;
},
onDataReady(files) {
onDataReady(traceName, files) {
this.traceName = traceName;
this.$store.dispatch('setFiles', files);
this.tagFile = this.tagFiles[0] ?? null;
@@ -281,6 +304,10 @@ export default {
FILE_TYPES.TAG_TRACE
);
},
editTraceName() {
this.editingTraceName = true;
}
},
computed: {
files() {
@@ -321,11 +348,18 @@ export default {
return fileTypes.includes(TRACE_TYPES.WINDOW_MANAGER)
&& fileTypes.includes(TRACE_TYPES.SURFACE_FLINGER);
},
traceNameForTitle() {
if (!this.dataLoaded) {
return undefined;
} else {
return this.traceName;
}
}
},
watch: {
title() {
document.title = this.title;
},
// title() {
// document.title = this.title;
// },
},
components: {
overlay: Overlay,
@@ -333,6 +367,7 @@ export default {
datainput: DataInput,
dataadb: DataAdb,
searchbar: Searchbar,
["vue-title"]: titleComponent,
},
};
</script>
@@ -429,4 +464,37 @@ h1 {
hyphens: auto;
padding: 10px 10px 10px 10px;
}
</style>
.trace-name {
flex: 1;
display: flex;
align-items: center;
align-content: center;
justify-content: center;
font-family: 'Open Sans', sans-serif;
font-size: 1rem;
}
.md-icon.edit-trace-name-btn {
color: rgba(0, 0, 0, 0.6)!important;
font-size: 1rem!important;
margin-bottom: 0.1rem;
}
.md-icon.edit-trace-name-btn:hover {
cursor: pointer;
}
.trace-name-editable {
all: unset;
cursor: default;
}
.edit-trace-name-dialog .md-dialog-container {
min-width: 350px;
}
.md-overlay.md-dialog-overlay {
z-index: 10;
}
</style>

View File

@@ -423,18 +423,18 @@ export default {
}
this.status = STATES.LOAD_DATA;
this.callProxy('POST', `${PROXY_ENDPOINTS.DUMP}${this.deviceId()}/`, this, function(request, view) {
view.loadFile(requested, 0);
view.loadFile(requested, 0, "dump");
}, null, requested);
},
endTrace() {
this.status = STATES.LOAD_DATA;
this.callProxy('POST', `${PROXY_ENDPOINTS.END_TRACE}${this.deviceId()}/`, this, function(request, view) {
view.loadFile(view.toTrace(), 0);
view.loadFile(view.toTrace(), 0, "trace");
});
this.recordNewEvent("Ended Trace");
},
loadFile(files, idx) {
this.callProxy('GET', `${PROXY_ENDPOINTS.FETCH}${this.deviceId()}/${files[idx]}/`, this, function(request, view) {
loadFile(files, idx, traceType) {
this.callProxy('GET', `${PROXY_ENDPOINTS.FETCH}${this.deviceId()}/${files[idx]}/`, this, (request, view) => {
try {
const enc = new TextDecoder('utf-8');
const resp = enc.decode(request.response);
@@ -455,9 +455,12 @@ export default {
}
if (idx < files.length - 1) {
view.loadFile(files, idx + 1);
view.loadFile(files, idx + 1, traceType);
} else {
view.$emit('dataReady', view.dataFiles);
const currentDate = new Date().toISOString();
view.$emit('dataReady',
`winscope-${traceType}-${currentDate}`,
view.dataFiles);
}
} catch (err) {
console.error(err);

View File

@@ -19,7 +19,7 @@
<div class="md-title">Open files</div>
</md-card-header>
<md-card-content>
<div class="dropbox" @click="$refs.fileUpload.click()">
<div class="dropbox" @click="$refs.fileUpload.click()" ref="dropbox">
<md-list
class="uploaded-files"
v-show="Object.keys(dataFiles).length > 0"
@@ -144,12 +144,19 @@ export default {
snackbarDuration: 3500,
snackbarText: '',
fetchingSnackbarText: 'Fetching files...',
traceName: undefined,
};
},
props: ['store'],
created() {
// Attempt to load files from extension if present
this.loadFilesFromExtension();
},
mounted() {
this.handleDropboxDragEvents();
},
beforeUnmount() {
},
methods: {
showSnackbarMessage(message, duration) {
@@ -180,6 +187,32 @@ export default {
},
});
},
handleDropboxDragEvents() {
// Counter used to keep track of when we actually exit the dropbox area
// When we drag over a child of the dropbox area the dragenter event will
// be called again and subsequently the dragleave so we don't want to just
// remove the class on the dragleave event.
let dropboxDragCounter = 0;
console.log(this.$refs["dropbox"])
this.$refs["dropbox"].addEventListener('dragenter', e => {
dropboxDragCounter++;
this.$refs["dropbox"].classList.add('dragover');
});
this.$refs["dropbox"].addEventListener('dragleave', e => {
dropboxDragCounter--;
if (dropboxDragCounter == 0) {
this.$refs["dropbox"].classList.remove('dragover');
}
});
this.$refs["dropbox"].addEventListener('drop', e => {
dropboxDragCounter = 0;
this.$refs["dropbox"].classList.remove('dragover');
});
},
/**
* Attempt to load files from the extension if present.
*
@@ -264,6 +297,21 @@ export default {
this.processFiles(files);
},
async processFiles(files) {
console.log("Object.keys(this.dataFiles).length", Object.keys(this.dataFiles).length)
// The trace name to use if we manage to load the archive without errors.
let tmpTraceName;
if (Object.keys(this.dataFiles).length > 0) {
// We have already loaded some files so only want to use the name of
// this archive as the name of the trace if we override all loaded files
} else {
// No files have been uploaded yet so if we are uploading only 1 archive
// we want to use it's name as the trace name
if (files.length == 1 && this.isArchive(files[0])) {
tmpTraceName = this.getFileNameWithoutZipExtension(files[0])
}
}
let error;
const decodedFiles = [];
for (const file of files) {
@@ -332,6 +380,19 @@ export default {
if (overriddenFileTypes.size > 0) {
this.displayFilesOverridenWarning(overriddenFiles);
}
if (tmpTraceName !== undefined) {
this.traceName = tmpTraceName;
}
},
getFileNameWithoutZipExtension(file) {
const fileNameSplitOnDot = file.name.split('.')
if (fileNameSplitOnDot.slice(-1)[0] == 'zip') {
return fileNameSplitOnDot.slice(0,-1).join('.');
} else {
return file.name;
}
},
/**
@@ -451,8 +512,8 @@ export default {
return undefined;
},
async addFile(file) {
const decodedFiles = [];
isArchive(file) {
const type = this.fileType;
const extension = this.getFileExtensions(file);
@@ -461,9 +522,15 @@ export default {
// 'application/zip' because when loaded from the extension the type is
// incorrect. See comment in loadFilesFromExtension() for more
// information.
if (type === 'bugreport' ||
return type === 'bugreport' ||
(type === 'auto' && (extension === 'zip' ||
file.type === 'application/zip'))) {
file.type === 'application/zip'))
},
async addFile(file) {
const decodedFiles = [];
if (this.isArchive(file)) {
const results = await this.decodeArchive(file);
decodedFiles.push(...results);
} else {
@@ -541,7 +608,7 @@ export default {
this.$delete(this.dataFiles, typeName);
},
onSubmit() {
this.$emit('dataReady',
this.$emit('dataReady', this.formattedTraceName,
Object.keys(this.dataFiles).map((key) => this.dataFiles[key]));
},
},
@@ -549,6 +616,14 @@ export default {
dataReady: function() {
return Object.keys(this.dataFiles).length > 0;
},
formattedTraceName() {
if (this.traceName === undefined) {
return 'winscope-trace';
} else {
return this.traceName;
}
}
},
components: {
'flat-card': FlatCard,
@@ -557,7 +632,7 @@ export default {
</script>
<style>
.dropbox:hover {
.dropbox:hover, .dropbox.dragover {
background: rgb(224, 224, 224);
}

View File

@@ -37,7 +37,7 @@ export default {
margin: 0;
padding: 10px 0;
min-width: 10rem;
z-index: 1500;
z-index: 10;
position: fixed;
list-style: none;
box-sizing: border-box;

View File

@@ -743,6 +743,7 @@ export default {
.overlay-content {
flex-grow: 1;
z-index: 10;
}
.bottom-nav {

View File

@@ -136,7 +136,7 @@ export default {
cursorMask.style.position = 'fixed';
cursorMask.style.top = '0';
cursorMask.style.left = '0';
cursorMask.style['z-index'] = '1000';
cursorMask.style['z-index'] = '10';
return {
inject: () => {

View File

@@ -166,7 +166,7 @@ export default {
'left': 0,
'height': '100vh',
'width': '100vw',
'z-index': 100,
'z-index': 10,
'cursor': 'crosshair',
});
@@ -350,7 +350,7 @@ export default {
.selection, .selection-intent {
position: absolute;
z-index: 100;
z-index: 10;
background: rgba(255, 36, 36, 0.5);
pointer-events: none;
}

View File

@@ -0,0 +1,31 @@
<script>
export default {
name: 'vue-title',
props: ['appName', 'traceName'],
watch: {
traceName: {
immediate: true,
handler() {
this.updatePageTitle();
}
},
appName: {
immediate: true,
handler() {
this.updatePageTitle();
}
}
},
methods: {
updatePageTitle() {
if (this.traceName == null || this.traceName == "") {
document.title = this.appName;
} else {
document.title = this.traceName;
}
}
},
render () {
},
}
</script>

View File

@@ -55,7 +55,7 @@ export default {
default: return fileName
}
},
async downloadAsZip(traces) {
async downloadAsZip(traces, traceName='winscope') {
const zip = new JSZip();
this.recordButtonClickedEvent("Download All")
@@ -70,7 +70,7 @@ export default {
const zipFile = await zip.generateAsync({type: 'blob'});
this.saveAs(zipFile, 'winscope.zip');
this.saveAs(zipFile, `${traceName}.zip`);
},
},
};