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:
committed by
Android (Google) Code Review
commit
a593541a36
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -743,6 +743,7 @@ export default {
|
||||
|
||||
.overlay-content {
|
||||
flex-grow: 1;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.bottom-nav {
|
||||
|
||||
@@ -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: () => {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
31
tools/winscope/src/Title.vue
Normal file
31
tools/winscope/src/Title.vue
Normal 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>
|
||||
@@ -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`);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user