Merge "Refactor and simplify layouts and css styles"
This commit is contained in:
@@ -11,6 +11,7 @@ import { MatProgressSpinnerModule } from "@angular/material/progress-spinner";
|
||||
import { MatProgressBarModule } from "@angular/material/progress-bar";
|
||||
import { FormsModule } from "@angular/forms";
|
||||
import { MatCheckboxModule } from "@angular/material/checkbox";
|
||||
import { MatDividerModule } from "@angular/material/divider";
|
||||
import { MatFormFieldModule } from "@angular/material/form-field";
|
||||
import { MatIconModule } from "@angular/material/icon";
|
||||
import { MatInputModule } from "@angular/material/input";
|
||||
@@ -91,6 +92,7 @@ import { ViewerWindowManagerComponent } from "viewers/viewer_window_manager/view
|
||||
FormsModule,
|
||||
MatListModule,
|
||||
MatCheckboxModule,
|
||||
MatDividerModule,
|
||||
MatIconModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatProgressBarModule,
|
||||
|
||||
@@ -55,7 +55,7 @@ describe("AdbProxyComponent", () => {
|
||||
it("check correct icon and message displays if no proxy", () => {
|
||||
component.proxy.setState(ProxyState.NO_PROXY);
|
||||
fixture.detectChanges();
|
||||
expect(htmlElement.querySelector(".further-adb-info")?.innerHTML).toContain("Launch the Winscope ADB Connect proxy");
|
||||
expect(htmlElement.querySelector(".further-adb-info-text")?.innerHTML).toContain("Launch the Winscope ADB Connect proxy");
|
||||
});
|
||||
|
||||
it("check correct icon and message displays if invalid proxy", () => {
|
||||
|
||||
@@ -19,45 +19,58 @@ import { proxyClient, ProxyClient, ProxyState } from "trace_collection/proxy_cli
|
||||
@Component({
|
||||
selector: "adb-proxy",
|
||||
template: `
|
||||
<div *ngIf="proxy.state===states.NO_PROXY" class="further-adb-info">
|
||||
<p class="mat-body-1">Launch the Winscope ADB Connect proxy to capture traces directly from your browser.</p>
|
||||
<p class="mat-body-1">Python 3.5+ and ADB are required.</p>
|
||||
<p class="mat-body-1">Run: <code>python3 $ANDROID_BUILD_TOP/development/tools/winscope-ng/src/adb/winscope_proxy.py</code></p>
|
||||
<p class="mat-body-1">Or get it from the AOSP repository.</p>
|
||||
<div>
|
||||
<button color="primary" mat-stroked-button (click)="downloadFromAosp()">Download from AOSP</button>
|
||||
<button color="primary" mat-stroked-button class="retry" (click)="restart()">Retry</button>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container [ngSwitch]="proxy.state">
|
||||
<ng-container *ngSwitchCase="states.NO_PROXY">
|
||||
<div class="further-adb-info-text">
|
||||
<p class="mat-body-1">Launch the Winscope ADB Connect proxy to capture traces directly from your browser.</p>
|
||||
<p class="mat-body-1">Python 3.5+ and ADB are required.</p>
|
||||
<p class="mat-body-1">Run: <code>python3 $ANDROID_BUILD_TOP/development/tools/winscope-ng/src/adb/winscope_proxy.py</code></p>
|
||||
<p class="mat-body-1">Or get it from the AOSP repository.</p>
|
||||
</div>
|
||||
|
||||
<div *ngIf="proxy.state===states.INVALID_VERSION" class="further-adb-info">
|
||||
<p class="icon-information mat-body-1">
|
||||
<mat-icon class="adb-icon">update</mat-icon>
|
||||
<span class="adb-info">Your local proxy version is incompatible with Winscope.</span>
|
||||
</p>
|
||||
<p class="mat-body-1">Please update the proxy to version {{ proxyVersion }}.</p>
|
||||
<p class="mat-body-1">Run: <code>python3 $ANDROID_BUILD_TOP/development/tools/winscope-ng/src/adb/winscope_proxy.py</code></p>
|
||||
<p class="mat-body-1">Or get it from the AOSP repository.</p>
|
||||
<div>
|
||||
<button color="primary" mat-stroked-button (click)="downloadFromAosp()">Download from AOSP</button>
|
||||
<button color="primary" mat-stroked-button class="retry" (click)="restart()">Retry</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="further-adb-info-actions">
|
||||
<button color="primary" mat-stroked-button (click)="downloadFromAosp()">Download from AOSP</button>
|
||||
<button color="primary" mat-stroked-button class="retry" (click)="restart()">Retry</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<div *ngIf="proxy.state===states.UNAUTH" class="further-adb-info">
|
||||
<p class="icon-information mat-body-1">
|
||||
<mat-icon class="adb-icon">lock</mat-icon>
|
||||
<span class="adb-info">Proxy authorisation required.</span>
|
||||
</p>
|
||||
<p class="mat-body-1">Enter Winscope proxy token:</p>
|
||||
<mat-form-field class="proxy-key-field">
|
||||
<input matInput [(ngModel)]="proxyKeyItem" name="proxy-key"/>
|
||||
</mat-form-field>
|
||||
<p class="mat-body-1">The proxy token is printed to console on proxy launch, copy and paste it above.</p>
|
||||
<div>
|
||||
<button color="primary" mat-stroked-button class="retry" (click)="restart()">Connect</button>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngSwitchCase="states.INVALID_VERSION">
|
||||
<div class="further-adb-info-text">
|
||||
<p class="icon-information mat-body-1">
|
||||
<mat-icon class="adb-icon">update</mat-icon>
|
||||
<span class="adb-info">Your local proxy version is incompatible with Winscope.</span>
|
||||
</p>
|
||||
<p class="mat-body-1">Please update the proxy to version {{ proxyVersion }}.</p>
|
||||
<p class="mat-body-1">Run: <code>python3 $ANDROID_BUILD_TOP/development/tools/winscope-ng/src/adb/winscope_proxy.py</code></p>
|
||||
<p class="mat-body-1">Or get it from the AOSP repository.</p>
|
||||
</div>
|
||||
|
||||
<div class="further-adb-info-actions">
|
||||
<button color="primary" mat-stroked-button (click)="downloadFromAosp()">Download from AOSP</button>
|
||||
<button color="primary" mat-stroked-button class="retry" (click)="restart()">Retry</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="states.UNAUTH">
|
||||
<div class="further-adb-info-text">
|
||||
<p class="icon-information mat-body-1">
|
||||
<mat-icon class="adb-icon">lock</mat-icon>
|
||||
<span class="adb-info">Proxy authorisation required.</span>
|
||||
</p>
|
||||
<p class="mat-body-1">Enter Winscope proxy token:</p>
|
||||
<mat-form-field>
|
||||
<input matInput [(ngModel)]="proxyKeyItem" name="proxy-key"/>
|
||||
</mat-form-field>
|
||||
<p class="mat-body-1">The proxy token is printed to console on proxy launch, copy and paste it above.</p>
|
||||
</div>
|
||||
|
||||
<div class="further-adb-info-actions">
|
||||
<button color="primary" mat-stroked-button class="retry" (click)="restart()">Connect</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchDefault></ng-container>
|
||||
</ng-container>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
@@ -66,14 +79,21 @@ import { proxyClient, ProxyClient, ProxyState } from "trace_collection/proxy_cli
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
.further-adb-info {
|
||||
.further-adb-info-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-wrap: break-word;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.further-adb-info p {
|
||||
margin: 10px 0;
|
||||
.further-adb-info-actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
.proxy-key-field {
|
||||
width: 30rem
|
||||
.adb-info {
|
||||
margin-left: 5px;
|
||||
}
|
||||
`
|
||||
]
|
||||
|
||||
@@ -18,8 +18,9 @@ import {ComponentFixture, TestBed, ComponentFixtureAutoDetect} from "@angular/co
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { MatCardModule } from "@angular/material/card";
|
||||
import { MatButtonModule } from "@angular/material/button";
|
||||
import { MatGridListModule } from "@angular/material/grid-list";
|
||||
import { MatDividerModule } from "@angular/material/divider";
|
||||
import { MatSliderModule } from "@angular/material/slider";
|
||||
import { MatSnackBarModule } from "@angular/material/snack-bar";
|
||||
import { MatToolbarModule } from "@angular/material/toolbar";
|
||||
|
||||
import { AppComponent } from "./app.component";
|
||||
@@ -45,8 +46,9 @@ describe("AppComponent", () => {
|
||||
CommonModule,
|
||||
MatCardModule,
|
||||
MatButtonModule,
|
||||
MatGridListModule,
|
||||
MatDividerModule,
|
||||
MatSliderModule,
|
||||
MatSnackBarModule,
|
||||
MatToolbarModule
|
||||
],
|
||||
declarations: [
|
||||
@@ -76,21 +78,24 @@ describe("AppComponent", () => {
|
||||
});
|
||||
|
||||
it("renders the page title", () => {
|
||||
expect(htmlElement.querySelector("#app-title")?.innerHTML).toContain("Winscope");
|
||||
expect(htmlElement.querySelector(".app-title")?.innerHTML).toContain("Winscope");
|
||||
});
|
||||
|
||||
it("displays correct elements when no data loaded", async () => {
|
||||
it("displays correct elements when no data loaded", () => {
|
||||
component.dataLoaded = false;
|
||||
fixture.detectChanges();
|
||||
expect(htmlElement.querySelector(".welcome-info")).toBeTruthy();
|
||||
expect(htmlElement.querySelector("#viewers")).toBeNull();
|
||||
expect(htmlElement.querySelector(".collect-traces-card")).toBeTruthy();
|
||||
expect(htmlElement.querySelector(".upload-traces-card")).toBeTruthy();
|
||||
expect(htmlElement.querySelector(".viewers")).toBeFalsy();
|
||||
});
|
||||
|
||||
it("displays correct elements when data loaded", async () => {
|
||||
it("displays correct elements when data loaded", () => {
|
||||
component.dataLoaded = true;
|
||||
fixture.detectChanges();
|
||||
expect(htmlElement.querySelector("#collect-traces-card")).toBeFalsy();
|
||||
expect(htmlElement.querySelector("#upload-traces-card")).toBeFalsy();
|
||||
expect(htmlElement.querySelector("#viewers")).toBeTruthy();
|
||||
expect(htmlElement.querySelector(".welcome-info")).toBeFalsy();
|
||||
expect(htmlElement.querySelector(".collect-traces-card")).toBeFalsy();
|
||||
expect(htmlElement.querySelector(".upload-traces-card")).toBeFalsy();
|
||||
expect(htmlElement.querySelector(".viewers")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,94 +32,96 @@ import { ViewerScreenRecordingComponent } from "viewers/viewer_screen_recording/
|
||||
@Component({
|
||||
selector: "app-root",
|
||||
template: `
|
||||
<mat-toolbar class="app-toolbar">
|
||||
<p id="app-title" class="mat-display-1">Winscope</p>
|
||||
<span class="toolbar-wrapper">
|
||||
<button *ngIf="dataLoaded" color="primary" mat-stroked-button (click)="toggleTimestamp()">Start/End Timestamp</button>
|
||||
<button *ngIf="dataLoaded" color="primary" mat-stroked-button (click)="onUploadNewClick()">Upload New</button>
|
||||
</span>
|
||||
<mat-toolbar>
|
||||
<span class="app-title">Winscope</span>
|
||||
|
||||
<ng-container *ngIf="dataLoaded">
|
||||
<button color="primary" mat-stroked-button (click)="toggleTimestamp()">
|
||||
Start/End Timestamp
|
||||
</button>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<button color="primary" mat-stroked-button (click)="onUploadNewClick()">
|
||||
Upload New
|
||||
</button>
|
||||
</ng-container>
|
||||
</mat-toolbar>
|
||||
|
||||
<h1 *ngIf="!dataLoaded" class="welcome-info mat-headline">Welcome to Winscope. Please select source to view traces.</h1>
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div *ngIf="!dataLoaded" class="card-grid">
|
||||
<mat-card id="collect-traces-card" class="homepage-card">
|
||||
<collect-traces [traceCoordinator]="traceCoordinator" (dataLoadedChange)="onDataLoadedChange($event)" [store]="store"></collect-traces>
|
||||
</mat-card>
|
||||
<mat-card id="upload-traces-card" class="homepage-card">
|
||||
<upload-traces [traceCoordinator]="traceCoordinator" (dataLoadedChange)="onDataLoadedChange($event)"></upload-traces>
|
||||
</mat-card>
|
||||
</div>
|
||||
<ng-container *ngIf="dataLoaded; else noLoadedTracesBlock">
|
||||
<trace-view
|
||||
class="viewers"
|
||||
[viewers]="allViewers"
|
||||
[store]="store"
|
||||
(downloadTracesButtonClick)="onDownloadTracesButtonClick()"
|
||||
></trace-view>
|
||||
|
||||
<trace-view
|
||||
*ngIf="dataLoaded"
|
||||
id="viewers"
|
||||
[viewers]="allViewers"
|
||||
[store]="store"
|
||||
(downloadTracesButtonClick)="onDownloadTracesButtonClick()"
|
||||
></trace-view>
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div *ngIf="dataLoaded" id="timescrub">
|
||||
<mat-slider
|
||||
class="timescrub"
|
||||
color="primary"
|
||||
class="time-slider"
|
||||
step="1"
|
||||
min="0"
|
||||
[max]="this.allTimestamps.length-1"
|
||||
[max]="this.allTimestamps.length - 1"
|
||||
aria-label="units"
|
||||
[value]="currentTimestampIndex"
|
||||
(input)="updateCurrentTimestamp($event)"
|
||||
></mat-slider>
|
||||
</div>
|
||||
<div id="timestamps">
|
||||
</ng-container>
|
||||
|
||||
<ng-template #noLoadedTracesBlock>
|
||||
<h1 class="welcome-info mat-headline">
|
||||
Welcome to Winscope. Please select source to view traces.
|
||||
</h1>
|
||||
|
||||
<div class="card-grid">
|
||||
<collect-traces
|
||||
class="collect-traces-card homepage-card"
|
||||
[traceCoordinator]="traceCoordinator"
|
||||
(dataLoadedChange)="onDataLoadedChange($event)"
|
||||
[store]="store"
|
||||
></collect-traces>
|
||||
|
||||
<upload-traces
|
||||
class="upload-traces-card homepage-card"
|
||||
[traceCoordinator]="traceCoordinator"
|
||||
(dataLoadedChange)="onDataLoadedChange($event)"
|
||||
></upload-traces>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<div class="timestamps">
|
||||
</div>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
.app-toolbar {
|
||||
background-color: white;
|
||||
border-bottom: 1px solid var(--default-border);
|
||||
}
|
||||
#app-title {
|
||||
margin: 12px 0;
|
||||
}
|
||||
.toolbar-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.app-title {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.welcome-info {
|
||||
margin: 16px 0;
|
||||
margin: 16px 0 6px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.homepage-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
margin: 10px;
|
||||
overflow: auto;
|
||||
border: 1px solid var(--default-border);
|
||||
}
|
||||
|
||||
.homepage-card mat-card-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
}
|
||||
#viewers {
|
||||
.spacer {
|
||||
flex: 1;
|
||||
}
|
||||
.viewers {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
}
|
||||
#timescrub {
|
||||
padding: 8px;
|
||||
border-top: 1px solid var(--default-border);
|
||||
}
|
||||
.time-slider {
|
||||
width: 100%
|
||||
.timescrub {
|
||||
margin: 8px;
|
||||
}
|
||||
`
|
||||
],
|
||||
|
||||
@@ -22,6 +22,7 @@ import { WebAdbComponent } from "./web_adb.component";
|
||||
import { TraceConfigComponent } from "./trace_config.component";
|
||||
import { MatListModule } from "@angular/material/list";
|
||||
import { MatButtonModule } from "@angular/material/button";
|
||||
import { MatDividerModule } from "@angular/material/divider";
|
||||
import { MatProgressBarModule } from "@angular/material/progress-bar";
|
||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
@@ -39,6 +40,7 @@ describe("CollectTracesComponent", () => {
|
||||
MatCardModule,
|
||||
MatListModule,
|
||||
MatButtonModule,
|
||||
MatDividerModule,
|
||||
MatProgressBarModule,
|
||||
BrowserAnimationsModule,
|
||||
MatSnackBarModule
|
||||
@@ -64,7 +66,7 @@ describe("CollectTracesComponent", () => {
|
||||
|
||||
it("renders the expected card title", () => {
|
||||
fixture.detectChanges();
|
||||
expect(htmlElement.querySelector("#title")?.innerHTML).toContain("Collect Traces");
|
||||
expect(htmlElement.querySelector(".title")?.innerHTML).toContain("Collect Traces");
|
||||
});
|
||||
|
||||
it("displays connecting message", () => {
|
||||
@@ -78,9 +80,9 @@ describe("CollectTracesComponent", () => {
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then( () => {
|
||||
expect(htmlElement.querySelector(".set-up-adb")).toBeTruthy();
|
||||
const proxyTab: HTMLButtonElement | null = htmlElement.querySelector("#proxy-tab");
|
||||
const proxyTab: HTMLButtonElement | null = htmlElement.querySelector(".proxy-tab");
|
||||
expect(proxyTab).toBeInstanceOf(HTMLButtonElement);
|
||||
const webTab: HTMLButtonElement | null = htmlElement.querySelector("#web-tab");
|
||||
const webTab: HTMLButtonElement | null = htmlElement.querySelector(".web-tab");
|
||||
expect(webTab).toBeInstanceOf(HTMLButtonElement);
|
||||
});
|
||||
});
|
||||
@@ -110,7 +112,7 @@ describe("CollectTracesComponent", () => {
|
||||
component.isAdbProxy = true;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
const webTab: HTMLButtonElement | null = htmlElement.querySelector("#web-tab");
|
||||
const webTab: HTMLButtonElement | null = htmlElement.querySelector(".web-tab");
|
||||
expect(webTab).toBeInstanceOf(HTMLButtonElement);
|
||||
webTab?.dispatchEvent(new Event("click"));
|
||||
fixture.whenStable().then(() => {
|
||||
@@ -124,7 +126,7 @@ describe("CollectTracesComponent", () => {
|
||||
component.connect.devices = jasmine.createSpy().and.returnValue({});
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then( () => {
|
||||
const el = htmlElement.querySelector("devices-connecting");
|
||||
const el = htmlElement.querySelector(".devices-connecting");
|
||||
expect(el).toBeTruthy();
|
||||
expect(el?.innerHTML).toContain("No devices detected");
|
||||
});
|
||||
@@ -135,7 +137,7 @@ describe("CollectTracesComponent", () => {
|
||||
component.connect.devices = jasmine.createSpy().and.returnValue({"35562": {model: "Pixel 6", authorised:true}});
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then( () => {
|
||||
const el = htmlElement.querySelector("devices-connecting");
|
||||
const el = htmlElement.querySelector(".devices-connecting");
|
||||
expect(el).toBeTruthy();
|
||||
expect(el?.innerHTML).toContain("Connected devices:");
|
||||
expect(el?.innerHTML).toContain("Pixel 6");
|
||||
@@ -148,7 +150,7 @@ describe("CollectTracesComponent", () => {
|
||||
component.connect.devices = jasmine.createSpy().and.returnValue({"35562": {model: "Pixel 6", authorised:false}});
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then( () => {
|
||||
const el = htmlElement.querySelector("devices-connecting");
|
||||
const el = htmlElement.querySelector(".devices-connecting");
|
||||
expect(el).toBeTruthy();
|
||||
expect(el?.innerHTML).toContain("Connected devices:");
|
||||
expect(el?.innerHTML).toContain("unauthorised");
|
||||
@@ -164,16 +166,16 @@ describe("CollectTracesComponent", () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.whenStable().then( () => {
|
||||
const el = htmlElement.querySelector("trace-collection-config");
|
||||
const el = htmlElement.querySelector(".trace-collection-config");
|
||||
expect(el).toBeTruthy();
|
||||
expect(el?.innerHTML).toContain("smartphone");
|
||||
expect(el?.innerHTML).toContain("Pixel 6");
|
||||
expect(el?.innerHTML).toContain("35562");
|
||||
|
||||
const traceSection = htmlElement.querySelector("trace-section");
|
||||
const traceSection = htmlElement.querySelector(".trace-section");
|
||||
expect(traceSection).toBeTruthy();
|
||||
|
||||
const dumpSection = htmlElement.querySelector("dump-section");
|
||||
const dumpSection = htmlElement.querySelector(".dump-section");
|
||||
expect(dumpSection).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,89 +28,132 @@ import { ParserErrorSnackBarComponent } from "./parser_error_snack_bar_component
|
||||
@Component({
|
||||
selector: "collect-traces",
|
||||
template: `
|
||||
<mat-card-title id="title">Collect Traces</mat-card-title>
|
||||
<mat-card-content>
|
||||
<mat-card class="collect-card">
|
||||
<mat-card-title class="title">Collect Traces</mat-card-title>
|
||||
|
||||
<p *ngIf="connect.isConnectingState()" class="connecting-message mat-body-1">Connecting...</p>
|
||||
<mat-card-content class="collect-card-content">
|
||||
<p *ngIf="connect.isConnectingState()" class="connecting-message mat-body-1">Connecting...</p>
|
||||
|
||||
<div *ngIf="!connect.adbSuccess()" class="set-up-adb">
|
||||
<button id="proxy-tab" color="primary" mat-stroked-button [ngClass]="tabClass(true)" (click)="displayAdbProxyTab()">ADB Proxy</button>
|
||||
<!-- <button id="web-tab" color="primary" mat-raised-button [ngClass]="tabClass(false)" (click)="displayWebAdbTab()">Web ADB</button> -->
|
||||
<adb-proxy *ngIf="isAdbProxy" [(proxy)]="connect.proxy!" (addKey)="onAddKey($event)"></adb-proxy>
|
||||
<!-- <web-adb *ngIf="!isAdbProxy"></web-adb> TODO: fix web adb workflow -->
|
||||
</div>
|
||||
|
||||
<div id="devices-connecting" *ngIf="connect.isDevicesState()">
|
||||
<p class="mat-body-1"> {{ objectKeys(connect.devices()).length > 0 ? "Connected devices:" : "No devices detected" }}</p>
|
||||
<mat-list *ngIf="objectKeys(connect.devices()).length > 0">
|
||||
<mat-list-item *ngFor="let deviceId of objectKeys(connect.devices())" (click)="connect.selectDevice(deviceId)">
|
||||
<mat-icon>
|
||||
{{ connect.devices()[deviceId].authorised ? "smartphone" : "screen_lock_portrait" }}
|
||||
</mat-icon>
|
||||
{{ connect.devices()[deviceId].authorised ? connect.devices()[deviceId].model : "unauthorised" }} ({{ deviceId }})
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</div>
|
||||
|
||||
<div id="trace-collection-config" *ngIf="connect.isStartTraceState()">
|
||||
<mat-list>
|
||||
<mat-list-item>
|
||||
<mat-icon>smartphone</mat-icon>
|
||||
{{ connect.selectedDevice().model }} ({{ connect.selectedDeviceId() }})
|
||||
<button color="primary" class="change-btn" mat-button (click)="connect.resetLastDevice()">Change device</button>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
|
||||
<div class="trace-section">
|
||||
<trace-config [traces]="setTraces.DYNAMIC_TRACES"></trace-config>
|
||||
<button color="primary" mat-stroked-button class="start-btn" (click)="startTracing()">Start trace</button>
|
||||
<div *ngIf="!connect.adbSuccess()" class="set-up-adb">
|
||||
<button class="proxy-tab" color="primary" mat-stroked-button [ngClass]="tabClass(true)" (click)="displayAdbProxyTab()">ADB Proxy</button>
|
||||
<!-- <button class="web-tab" color="primary" mat-raised-button [ngClass]="tabClass(false)" (click)="displayWebAdbTab()">Web ADB</button> -->
|
||||
<adb-proxy *ngIf="isAdbProxy" [(proxy)]="connect.proxy!" (addKey)="onAddKey($event)"></adb-proxy>
|
||||
<!-- <web-adb *ngIf="!isAdbProxy"></web-adb> TODO: fix web adb workflow -->
|
||||
</div>
|
||||
|
||||
<div class="dump-section">
|
||||
<h3 class="mat-subheading-2">Dump targets</h3>
|
||||
<div class="selection">
|
||||
<mat-checkbox
|
||||
*ngFor="let dumpKey of objectKeys(setTraces.DUMPS)"
|
||||
color="primary"
|
||||
[(ngModel)]="setTraces.DUMPS[dumpKey].run"
|
||||
>{{setTraces.DUMPS[dumpKey].name}}</mat-checkbox>
|
||||
<div *ngIf="connect.isDevicesState()" class="devices-connecting">
|
||||
<p class="mat-body-1">{{ objectKeys(connect.devices()).length > 0 ? "Connected devices:" : "No devices detected" }}</p>
|
||||
<mat-list *ngIf="objectKeys(connect.devices()).length > 0">
|
||||
<mat-list-item *ngFor="let deviceId of objectKeys(connect.devices())" (click)="connect.selectDevice(deviceId)">
|
||||
<mat-icon matListIcon>
|
||||
{{ connect.devices()[deviceId].authorised ? "smartphone" : "screen_lock_portrait" }}
|
||||
</mat-icon>
|
||||
<p matLine>
|
||||
{{ connect.devices()[deviceId].authorised ? connect.devices()[deviceId].model : "unauthorised" }} ({{ deviceId }})
|
||||
</p>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</div>
|
||||
|
||||
<div *ngIf="connect.isStartTraceState()" class="trace-collection-config">
|
||||
<mat-list>
|
||||
<mat-list-item>
|
||||
<mat-icon matListIcon>smartphone</mat-icon>
|
||||
<p matLine>
|
||||
{{ connect.selectedDevice().model }} ({{ connect.selectedDeviceId() }})
|
||||
|
||||
<button color="primary" class="change-btn" mat-button (click)="connect.resetLastDevice()">Change device</button>
|
||||
</p>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
|
||||
<div class="trace-section">
|
||||
<trace-config [traces]="setTraces.DYNAMIC_TRACES"></trace-config>
|
||||
<button color="primary" class="start-btn" mat-stroked-button (click)="startTracing()">Start trace</button>
|
||||
</div>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div class="dump-section">
|
||||
<h3 class="mat-subheading-2">Dump targets</h3>
|
||||
<div class="selection">
|
||||
<mat-checkbox
|
||||
*ngFor="let dumpKey of objectKeys(setTraces.DUMPS)"
|
||||
color="primary"
|
||||
class="dump-checkbox"
|
||||
[(ngModel)]="setTraces.DUMPS[dumpKey].run"
|
||||
>{{setTraces.DUMPS[dumpKey].name}}</mat-checkbox>
|
||||
</div>
|
||||
<button color="primary" class="dump-btn" mat-stroked-button (click)="dumpState()">Dump state</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="connect.isErrorState()" class="unknown-error">
|
||||
<p class="error-wrapper mat-body-1">
|
||||
<mat-icon>error</mat-icon>
|
||||
Error:
|
||||
</p>
|
||||
<pre> {{ connect.proxy?.errorText }} </pre>
|
||||
<button color="primary" class="retry-btn" mat-raised-button (click)="connect.restart()">Retry</button>
|
||||
</div>
|
||||
<div *ngIf="connect.isErrorState()" class="unknown-error">
|
||||
<p class="error-wrapper mat-body-1">
|
||||
<mat-icon class="error-icon">error</mat-icon>
|
||||
Error:
|
||||
</p>
|
||||
<pre> {{ connect.proxy?.errorText }} </pre>
|
||||
<button color="primary" class="retry-btn" mat-raised-button (click)="connect.restart()">Retry</button>
|
||||
</div>
|
||||
|
||||
<div *ngIf="connect.isEndTraceState()" class="end-tracing">
|
||||
<p class="mat-body-1">Tracing...</p>
|
||||
<mat-progress-bar md-indeterminate value="{{connect.loadProgress}}"></mat-progress-bar>
|
||||
<button color="primary" class="end-btn" mat-raised-button (click)="endTrace()">End trace</button>
|
||||
</div>
|
||||
<div *ngIf="connect.isEndTraceState()" class="end-tracing">
|
||||
<p class="mat-body-1">Tracing...</p>
|
||||
<mat-progress-bar md-indeterminate value="{{connect.loadProgress}}"></mat-progress-bar>
|
||||
<button color="primary" class="end-btn" mat-raised-button (click)="endTrace()">End trace</button>
|
||||
</div>
|
||||
|
||||
<div *ngIf="connect.isLoadDataState()" class="load-data">
|
||||
<p class="mat-body-1">Loading data...</p>
|
||||
<mat-progress-bar md-indeterminate></mat-progress-bar>
|
||||
</div>
|
||||
<div *ngIf="connect.isLoadDataState()" class="load-data">
|
||||
<p class="mat-body-1">Loading data...</p>
|
||||
<mat-progress-bar md-indeterminate></mat-progress-bar>
|
||||
</div>
|
||||
|
||||
</mat-card-content>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
.change-btn {
|
||||
.change-btn, .retry-btn, .edn-btn {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.collect-card {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
margin: 10px;
|
||||
}
|
||||
.collect-card-content {
|
||||
overflow: auto;
|
||||
}
|
||||
.selection {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
.set-up-adb,
|
||||
.trace-collection-config,
|
||||
.trace-section,
|
||||
.dump-section,
|
||||
.end-tracing,
|
||||
.load-data,
|
||||
trace-config {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
.proxy-tab, .web-tab, .start-btn, .dump-btn, .end-btn {
|
||||
align-self: flex-start;
|
||||
}
|
||||
.error-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
.error-icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
`
|
||||
]
|
||||
})
|
||||
|
||||
@@ -22,7 +22,7 @@ import { ParserError, ParserErrorType } from "parsers/parser_factory";
|
||||
selector: "upload-snack-bar",
|
||||
template: `
|
||||
<div class="snack-bar-container">
|
||||
<p *ngFor="let msg of errorMessages" class="snack-bar-content mat-body-1">{{msg}}</p>
|
||||
<p *ngFor="let msg of errorMessages" class="mat-body-1">{{msg}}</p>
|
||||
<button color="primary" mat-button class="snack-bar-action" (click)="snackBarRef.dismiss()">
|
||||
Close
|
||||
</button>
|
||||
@@ -35,9 +35,6 @@ import { ParserError, ParserErrorType } from "parsers/parser_factory";
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
.snack-bar-content {
|
||||
color: white;
|
||||
}
|
||||
.snack-bar-action {
|
||||
margin-left: 12px;
|
||||
}
|
||||
@@ -61,7 +58,7 @@ export class ParserErrorSnackBarComponent {
|
||||
if (error.type === ParserErrorType.ALREADY_LOADED && error.traceType) {
|
||||
errorString = `Cannot load ${error.trace.name}; Already loaded a trace of type ${TRACE_INFO[error.traceType].name}`;
|
||||
} else if (error.type === ParserErrorType.UNSUPPORTED_FORMAT) {
|
||||
errorString = `Cannot load ${error.trace.name}; File format is unsupported`;
|
||||
errorString = `Cannot load ${error.trace.name}; File format is unsupported`;
|
||||
}
|
||||
return errorString;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { CommonModule } from "@angular/common";
|
||||
import {ComponentFixture, TestBed} from "@angular/core/testing";
|
||||
import {TraceConfigComponent} from "./trace_config.component";
|
||||
import { MatCheckboxModule } from "@angular/material/checkbox";
|
||||
import { MatDividerModule } from "@angular/material/divider";
|
||||
import { MatFormFieldModule } from "@angular/material/form-field";
|
||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { MatInputModule } from "@angular/material/input";
|
||||
@@ -33,6 +34,7 @@ describe("TraceConfigComponent", () => {
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatCheckboxModule,
|
||||
MatDividerModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatSelectModule,
|
||||
@@ -74,7 +76,7 @@ describe("TraceConfigComponent", () => {
|
||||
it("check that trace checkbox ticked on default run", () => {
|
||||
component.traces["layers_trace"].run = true;
|
||||
fixture.detectChanges();
|
||||
const box = htmlElement.querySelector(".trace-box");
|
||||
const box = htmlElement.querySelector(".trace-checkbox");
|
||||
expect(box?.innerHTML).toContain("aria-checked=\"true\"");
|
||||
expect(box?.innerHTML).toContain("layers_trace");
|
||||
});
|
||||
@@ -82,26 +84,34 @@ describe("TraceConfigComponent", () => {
|
||||
it("check that trace checkbox not ticked on default run", () => {
|
||||
component.traces["layers_trace"].run = false;
|
||||
fixture.detectChanges();
|
||||
const box = htmlElement.querySelector(".trace-box");
|
||||
const box = htmlElement.querySelector(".trace-checkbox");
|
||||
expect(box?.innerHTML).toContain("aria-checked=\"false\"");
|
||||
});
|
||||
|
||||
it("check that correct advanced enable config only shows", () => {
|
||||
it("check that correct advanced enable config shows", () => {
|
||||
component.traces["layers_trace"].config!.selectionConfigs = [];
|
||||
fixture.detectChanges();
|
||||
const adv = htmlElement.querySelector(".config-opt");
|
||||
expect(adv).toBeTruthy();
|
||||
expect(adv?.innerHTML).toContain("trace buffers");
|
||||
expect(adv?.innerHTML).not.toContain("tracing level");
|
||||
|
||||
const enable_config_opt = htmlElement.querySelector(".enable-config-opt");
|
||||
expect(enable_config_opt).toBeTruthy();
|
||||
expect(enable_config_opt?.innerHTML).toContain("trace buffers");
|
||||
expect(enable_config_opt?.innerHTML).not.toContain("tracing level");
|
||||
|
||||
const selection_config_opt = htmlElement.querySelector(".selection-config-opt");
|
||||
expect(selection_config_opt).toBeFalsy();
|
||||
});
|
||||
|
||||
it("check that correct advanced selection config shows", () => {
|
||||
component.traces["layers_trace"].config!.enableConfigs = [];
|
||||
fixture.detectChanges();
|
||||
const adv = htmlElement.querySelector(".config-opt");
|
||||
expect(adv).toBeTruthy();
|
||||
expect(adv?.innerHTML).not.toContain("trace buffers");
|
||||
expect(adv?.innerHTML).toContain("tracing level");
|
||||
|
||||
const enable_config_opt = htmlElement.querySelector(".enable-config-opt");
|
||||
expect(enable_config_opt).toBeFalsy();
|
||||
|
||||
const selection_config_opt = htmlElement.querySelector(".selection-config-opt");
|
||||
expect(selection_config_opt).toBeTruthy();
|
||||
expect(selection_config_opt?.innerHTML).not.toContain("trace buffers");
|
||||
expect(selection_config_opt?.innerHTML).toContain("tracing level");
|
||||
});
|
||||
|
||||
it("check that changing enable config causes box to change", async () => {
|
||||
@@ -116,8 +126,7 @@ describe("TraceConfigComponent", () => {
|
||||
expect(htmlElement.querySelector(".config-selection")?.innerHTML).toContain("value=\"debug\"");
|
||||
component.traces["layers_trace"].config!.selectionConfigs[0].value = "verbose";
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(htmlElement.querySelector(".config-selection")?.innerHTML).toContain("value=\"verbose\"");
|
||||
});
|
||||
await fixture.whenStable();
|
||||
expect(htmlElement.querySelector(".config-selection")?.innerHTML).toContain("value=\"verbose\"");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,62 +19,65 @@ import { EnableConfiguration, SelectionConfiguration, TraceConfiguration, TraceC
|
||||
@Component({
|
||||
selector: "trace-config",
|
||||
template: `
|
||||
<div class="card-block">
|
||||
<h3 class="mat-subheading-2">Trace targets</h3>
|
||||
<div class="checkboxes">
|
||||
<h3 class="mat-subheading-2">Trace targets</h3>
|
||||
|
||||
<div class="checkboxes">
|
||||
<mat-checkbox
|
||||
*ngFor="let traceKey of objectKeys(traces)"
|
||||
color="primary"
|
||||
class="trace-checkbox"
|
||||
[checked]="traces[traceKey].run"
|
||||
[indeterminate]="traces[traceKey].isTraceCollection ? someTraces(traces[traceKey]) : false"
|
||||
(change)="changeRunTrace($event.checked, traces[traceKey])"
|
||||
>{{traces[traceKey].name}}</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<ng-container *ngFor="let traceKey of advancedConfigTraces()">
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<h3 class="mat-subheading-2">{{traces[traceKey].name}} configuration</h3>
|
||||
|
||||
<div *ngIf="traces[traceKey].config?.enableConfigs.length > 0" class="enable-config-opt">
|
||||
<mat-checkbox
|
||||
*ngFor="let traceKey of objectKeys(traces)"
|
||||
*ngFor="let enableConfig of traceEnableConfigs(traces[traceKey])"
|
||||
color="primary"
|
||||
class="trace-box"
|
||||
[checked]="traces[traceKey].run"
|
||||
[indeterminate]="traces[traceKey].isTraceCollection ? someTraces(traces[traceKey]) : false"
|
||||
(change)="changeRunTrace($event.checked, traces[traceKey])"
|
||||
>{{traces[traceKey].name}}</mat-checkbox>
|
||||
class="enable-config"
|
||||
[disabled]="!traces[traceKey].run && !traces[traceKey].isTraceCollection"
|
||||
[(ngModel)]="enableConfig.enabled"
|
||||
(ngModelChange)="changeTraceCollectionConfig(traces[traceKey])"
|
||||
>{{enableConfig.name}}</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<ng-container *ngFor="let traceKey of advancedConfigTraces()">
|
||||
<h3 class="mat-subheading-2">{{traces[traceKey].name}} configuration</h3>
|
||||
<div *ngIf="traces[traceKey].config?.selectionConfigs.length > 0" class="selection-config-opt">
|
||||
<mat-form-field
|
||||
*ngFor="let selectionConfig of traceSelectionConfigs(traces[traceKey])"
|
||||
class="config-selection"
|
||||
appearance="fill">
|
||||
|
||||
<div *ngIf="traces[traceKey].config?.enableConfigs" class="config-opt">
|
||||
<mat-checkbox
|
||||
*ngFor="let enableConfig of traceEnableConfigs(traces[traceKey])"
|
||||
color="primary"
|
||||
class="enable-config"
|
||||
[disabled]="!traces[traceKey].run && !traces[traceKey].isTraceCollection"
|
||||
[(ngModel)]="enableConfig.enabled"
|
||||
(ngModelChange)="changeTraceCollectionConfig(traces[traceKey])"
|
||||
>{{enableConfig.name}}</mat-checkbox>
|
||||
<mat-label>{{selectionConfig.name}}</mat-label>
|
||||
|
||||
<div *ngIf="traces[traceKey].config?.selectionConfigs" class="config-opt">
|
||||
<mat-form-field
|
||||
*ngFor="let selectionConfig of traceSelectionConfigs(traces[traceKey])"
|
||||
class="config-selection"
|
||||
appearance="fill">
|
||||
<mat-label>{{selectionConfig.name}}</mat-label>
|
||||
<mat-select class="selected-value" [(value)]="selectionConfig.value" [disabled]="!traces[traceKey].run">
|
||||
<mat-option
|
||||
*ngFor="let option of selectionConfig.options"
|
||||
value="{{option}}"
|
||||
>{{ option }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
<mat-select class="selected-value" [(value)]="selectionConfig.value" [disabled]="!traces[traceKey].run">
|
||||
<mat-option
|
||||
*ngFor="let option of selectionConfig.options"
|
||||
value="{{option}}"
|
||||
>{{ option }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</ng-container>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
.card-block {
|
||||
margin: 15px;
|
||||
}
|
||||
.checkboxes {
|
||||
padding: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
column-gap: 10px;
|
||||
}
|
||||
.config-selection {
|
||||
margin: 0 5px;
|
||||
.enable-config-opt, .selection-config-opt {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
`
|
||||
]
|
||||
|
||||
@@ -17,6 +17,7 @@ import {CommonModule} from "@angular/common";
|
||||
import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA} from "@angular/core";
|
||||
import {ComponentFixture, TestBed} from "@angular/core/testing";
|
||||
import {MatCardModule} from "@angular/material/card";
|
||||
import {MatDividerModule} from "@angular/material/divider";
|
||||
import {TraceViewComponent} from "./trace_view.component";
|
||||
import {ViewerStub} from "viewers/viewer_stub";
|
||||
|
||||
@@ -30,7 +31,8 @@ describe("TraceViewComponent", () => {
|
||||
declarations: [TraceViewComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatCardModule
|
||||
MatCardModule,
|
||||
MatDividerModule
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
|
||||
}).compileComponents();
|
||||
|
||||
@@ -43,6 +43,7 @@ interface Tab extends View {
|
||||
(click)="downloadTracesButtonClick.emit()"
|
||||
>Download all traces</button>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="trace-view-content">
|
||||
</div>
|
||||
`,
|
||||
@@ -59,11 +60,9 @@ interface Tab extends View {
|
||||
}
|
||||
|
||||
.header-items-wrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tabs-navigation-bar {
|
||||
@@ -71,12 +70,8 @@ interface Tab extends View {
|
||||
}
|
||||
|
||||
.trace-view-content {
|
||||
height: 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.save-button {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
`
|
||||
]
|
||||
|
||||
@@ -26,7 +26,10 @@ describe("UploadTracesComponent", () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [MatCardModule, MatSnackBarModule],
|
||||
imports: [
|
||||
MatCardModule,
|
||||
MatSnackBarModule
|
||||
],
|
||||
providers: [MatSnackBar],
|
||||
declarations: [UploadTracesComponent],
|
||||
}).compileComponents();
|
||||
|
||||
@@ -24,9 +24,10 @@ import { ParserError } from "parsers/parser_factory";
|
||||
@Component({
|
||||
selector: "upload-traces",
|
||||
template: `
|
||||
<mat-card-title id="title">Upload Traces</mat-card-title>
|
||||
<mat-card-content>
|
||||
<div
|
||||
<mat-card class="upload-card">
|
||||
<mat-card-title class="title">Upload Traces</mat-card-title>
|
||||
|
||||
<mat-card-content
|
||||
class="drop-box"
|
||||
ref="drop-box"
|
||||
(dragleave)="onFileDragOut($event)"
|
||||
@@ -42,52 +43,78 @@ import { ParserError } from "parsers/parser_factory";
|
||||
#fileDropRef
|
||||
(change)="onInputFile($event)"
|
||||
/>
|
||||
|
||||
<mat-list *ngIf="this.loadedTraces.length > 0" class="uploaded-files">
|
||||
<mat-list-item *ngFor="let trace of loadedTraces">
|
||||
<mat-icon>{{TRACE_INFO[trace.type].icon}}</mat-icon>
|
||||
{{trace.name}} ({{TRACE_INFO[trace.type].name}})
|
||||
<button
|
||||
color="primary"
|
||||
mat-icon-button
|
||||
class="close-btn"
|
||||
(click)="onRemoveTrace($event, trace)"
|
||||
><mat-icon>close</mat-icon>
|
||||
<mat-icon matListIcon>
|
||||
{{TRACE_INFO[trace.type].icon}}
|
||||
</mat-icon>
|
||||
|
||||
<p matLine>
|
||||
{{trace.name}} ({{TRACE_INFO[trace.type].name}})
|
||||
</p>
|
||||
|
||||
<button color="primary" mat-icon-button (click)="onRemoveTrace($event, trace)">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
<p *ngIf="this.loadedTraces.length === 0" class="drop-info mat-body-1">Drag your .winscope file(s) or click to upload</p>
|
||||
</div>
|
||||
|
||||
<div *ngIf="this.loadedTraces.length > 0">
|
||||
<button color="primary" mat-raised-button class="load-btn" (click)="onLoadData()">View traces</button>
|
||||
<button color="primary" mat-stroked-button for="fileDropRef" (click)="fileDropRef.click()">Upload another file</button>
|
||||
<button color="primary" mat-stroked-button (click)="onClearData()">Clear all</button>
|
||||
<div *ngIf="this.loadedTraces.length === 0" class="drop-info">
|
||||
<p class="mat-body-1">
|
||||
Drag your .winscope file(s) or click to upload
|
||||
</p>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<div *ngIf="this.loadedTraces.length > 0" class="trace-actions-container">
|
||||
<button color="primary" mat-raised-button class="load-btn" (click)="onLoadData()">
|
||||
View traces
|
||||
</button>
|
||||
|
||||
<button color="primary" mat-stroked-button for="fileDropRef" (click)="fileDropRef.click()">
|
||||
Upload another file
|
||||
</button>
|
||||
|
||||
<button color="primary" mat-stroked-button (click)="onClearData()">
|
||||
Clear all
|
||||
</button>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
.drop-box {
|
||||
height: 400px;
|
||||
padding: 10px;
|
||||
.upload-card {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
outline: 2px dashed var(--default-border);
|
||||
outline-offset: -10px;
|
||||
margin: 10px;
|
||||
}
|
||||
.drop-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
border: 2px dashed var(--default-border);
|
||||
cursor: pointer;
|
||||
}
|
||||
.uploaded-files {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
.close-btn {
|
||||
margin-left: auto;
|
||||
flex: 400px;
|
||||
padding: 0;
|
||||
}
|
||||
.drop-info {
|
||||
flex: 400px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
pointer-events: none;
|
||||
margin: auto;
|
||||
}
|
||||
.trace-actions-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
`
|
||||
]
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
import {ComponentFixture, TestBed} from "@angular/core/testing";
|
||||
import {WebAdbComponent} from "./web_adb.component";
|
||||
import { MatIconModule } from "@angular/material/icon";
|
||||
import { MatCardModule } from "@angular/material/card";
|
||||
|
||||
describe("WebAdbComponent", () => {
|
||||
let fixture: ComponentFixture<WebAdbComponent>;
|
||||
@@ -25,7 +24,9 @@ describe("WebAdbComponent", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [MatIconModule, MatCardModule],
|
||||
imports: [
|
||||
MatIconModule
|
||||
],
|
||||
declarations: [WebAdbComponent],
|
||||
}).compileComponents();
|
||||
fixture = TestBed.createComponent(WebAdbComponent);
|
||||
|
||||
@@ -24,7 +24,7 @@ import {Component} from "@angular/core";
|
||||
</p>
|
||||
<p class="mat-body-1">Click the button below to follow instructions in the Chrome pop-up.</p>
|
||||
<p class="mat-body-1">Selecting a device will kill all existing ADB connections.</p>
|
||||
<button color="primary" mat-raised-button>Select a device</button>
|
||||
<button color="primary" class="web-select-btn" mat-raised-button>Select a device</button>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
@@ -33,6 +33,9 @@ import {Component} from "@angular/core";
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
.adb-info, .web-select-btn {
|
||||
margin-left: 5px;
|
||||
}
|
||||
`
|
||||
]
|
||||
})
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.svg">
|
||||
</head>
|
||||
<body>
|
||||
<body class="mat-app-background">
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -31,14 +31,17 @@ $theme: mat.define-light-theme((
|
||||
color: (
|
||||
primary: $primary,
|
||||
accent: $accent,
|
||||
)
|
||||
),
|
||||
density: 0,
|
||||
));
|
||||
|
||||
@include mat.core-theme($theme);
|
||||
|
||||
@include mat.button-theme($theme);
|
||||
@include mat.button-toggle-theme($theme);
|
||||
@include mat.card-theme($theme);
|
||||
@include mat.checkbox-theme($theme);
|
||||
@include mat.divider-theme($theme);
|
||||
@include mat.form-field-theme($theme);
|
||||
@include mat.grid-list-theme($theme);
|
||||
@include mat.icon-theme($theme);
|
||||
@@ -51,5 +54,5 @@ $theme: mat.define-light-theme((
|
||||
@include mat.slider-theme($theme);
|
||||
@include mat.snack-bar-theme($theme);
|
||||
@include mat.tabs-theme($theme);
|
||||
@include mat.tooltip-theme($theme);
|
||||
@include mat.toolbar-theme($theme);
|
||||
@include mat.tooltip-theme($theme);
|
||||
|
||||
@@ -37,22 +37,6 @@ app-root {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button.mat-raised-button {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
button.mat-stroked-button {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
mat-checkbox {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.card-grid {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -60,3 +44,7 @@ mat-icon {
|
||||
flex-direction: row;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
viewer-surface-flinger .properties-view .view-header {
|
||||
flex: 3;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ describe("winscope", () => {
|
||||
}),
|
||||
|
||||
it("has title", () => {
|
||||
const title = element(by.css("#app-title"));
|
||||
const title = element(by.css(".app-title"));
|
||||
expect(title.getText()).toContain("Winscope");
|
||||
});
|
||||
});
|
||||
@@ -21,6 +21,7 @@ import { CommonModule } from "@angular/common";
|
||||
import { MatInputModule } from "@angular/material/input";
|
||||
import { MatFormFieldModule } from "@angular/material/form-field";
|
||||
import { MatCheckboxModule } from "@angular/material/checkbox";
|
||||
import { MatDividerModule } from "@angular/material/divider";
|
||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { HierarchyTreeBuilder } from "test/unit/hierarchy_tree_builder";
|
||||
import { TreeComponent } from "viewers/components/tree.component";
|
||||
@@ -45,9 +46,10 @@ describe("HierarchyComponent", () => {
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatCheckboxModule,
|
||||
MatDividerModule,
|
||||
MatInputModule,
|
||||
MatFormFieldModule,
|
||||
MatCheckboxModule,
|
||||
BrowserAnimationsModule
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
|
||||
@@ -40,9 +40,8 @@ import { TableProperties } from "viewers/common/table_properties";
|
||||
</div>
|
||||
<div class="view-controls">
|
||||
<mat-checkbox
|
||||
color="primary"
|
||||
*ngFor="let option of objectKeys(userOptions)"
|
||||
class="trace-box"
|
||||
color="primary"
|
||||
[(ngModel)]="userOptions[option].enabled"
|
||||
(ngModelChange)="updateTree()"
|
||||
>{{userOptions[option].name}}</mat-checkbox>
|
||||
@@ -67,24 +66,23 @@ import { TableProperties } from "viewers/common/table_properties";
|
||||
></tree-node>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="hierarchy-content">
|
||||
<div class="tree-wrapper">
|
||||
<tree-view
|
||||
*ngIf="tree"
|
||||
[isFlattened]="isFlattened()"
|
||||
[isShaded]="true"
|
||||
[item]="tree"
|
||||
[dependencies]="dependencies"
|
||||
[store]="store"
|
||||
[useGlobalCollapsedState]="true"
|
||||
[itemsClickable]="true"
|
||||
[highlightedItems]="highlightedItems"
|
||||
[pinnedItems]="pinnedItems"
|
||||
(highlightedItemChange)="highlightedItemChange($event)"
|
||||
(pinnedItemChange)="pinnedItemChange($event)"
|
||||
(selectedTreeChange)="selectedTreeChange($event)"
|
||||
></tree-view>
|
||||
</div>
|
||||
<tree-view
|
||||
*ngIf="tree"
|
||||
[isFlattened]="isFlattened()"
|
||||
[isShaded]="true"
|
||||
[item]="tree"
|
||||
[dependencies]="dependencies"
|
||||
[store]="store"
|
||||
[useGlobalCollapsedState]="true"
|
||||
[itemsClickable]="true"
|
||||
[highlightedItems]="highlightedItems"
|
||||
[pinnedItems]="pinnedItems"
|
||||
(highlightedItemChange)="highlightedItemChange($event)"
|
||||
(pinnedItemChange)="pinnedItemChange($event)"
|
||||
(selectedTreeChange)="selectedTreeChange($event)"
|
||||
></tree-view>
|
||||
</div>
|
||||
`,
|
||||
styles: [
|
||||
@@ -92,8 +90,7 @@ import { TableProperties } from "viewers/common/table_properties";
|
||||
.view-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-bottom: 1px solid var(--default-border);
|
||||
padding-bottom: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.title-filter {
|
||||
@@ -107,6 +104,7 @@ import { TableProperties } from "viewers/common/table_properties";
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
.properties-table {
|
||||
@@ -114,9 +112,8 @@ import { TableProperties } from "viewers/common/table_properties";
|
||||
}
|
||||
|
||||
.hierarchy-content {
|
||||
height: 0;
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.pinned-items {
|
||||
@@ -125,8 +122,8 @@ import { TableProperties } from "viewers/common/table_properties";
|
||||
border: 2px solid yellow;
|
||||
}
|
||||
|
||||
.tree-wrapper {
|
||||
overflow-y: auto
|
||||
tree-view {
|
||||
overflow: auto;
|
||||
}
|
||||
`,
|
||||
nodeStyles
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
import {ComponentFixture, TestBed} from "@angular/core/testing";
|
||||
import { ImeAdditionalPropertiesComponent } from "./ime_additional_properties.component";
|
||||
import { MatCardModule } from "@angular/material/card";
|
||||
import { MatDividerModule } from "@angular/material/divider";
|
||||
|
||||
describe("ImeAdditionalPropertiesComponent", () => {
|
||||
let fixture: ComponentFixture<ImeAdditionalPropertiesComponent>;
|
||||
@@ -25,7 +25,7 @@ describe("ImeAdditionalPropertiesComponent", () => {
|
||||
beforeAll(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
MatCardModule,
|
||||
MatDividerModule
|
||||
],
|
||||
declarations: [
|
||||
ImeAdditionalPropertiesComponent
|
||||
|
||||
@@ -292,7 +292,7 @@ import { ViewerEvents } from "viewers/common/viewer_events";
|
||||
}
|
||||
|
||||
p.group-header {
|
||||
color: grey;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.left-column {
|
||||
|
||||
@@ -20,6 +20,7 @@ import { NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
import { MatInputModule } from "@angular/material/input";
|
||||
import { MatFormFieldModule } from "@angular/material/form-field";
|
||||
import { MatCheckboxModule } from "@angular/material/checkbox";
|
||||
import { MatDividerModule } from "@angular/material/divider";
|
||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { PropertyGroupsComponent } from "./property_groups.component";
|
||||
import { TreeComponent } from "./tree.component";
|
||||
@@ -44,6 +45,7 @@ describe("PropertiesComponent", () => {
|
||||
MatInputModule,
|
||||
MatFormFieldModule,
|
||||
MatCheckboxModule,
|
||||
MatDividerModule,
|
||||
BrowserAnimationsModule
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
|
||||
@@ -25,8 +25,10 @@ import { PropertiesTreeNode, Terminal} from "viewers/common/ui_tree_utils";
|
||||
<div class="view-header">
|
||||
<div class="title-filter">
|
||||
<h2 class="properties-title mat-title">Properties</h2>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>Filter...</mat-label>
|
||||
|
||||
<input
|
||||
matInput
|
||||
[(ngModel)]="filterString"
|
||||
@@ -35,24 +37,29 @@ import { PropertiesTreeNode, Terminal} from "viewers/common/ui_tree_utils";
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="view-controls">
|
||||
<mat-checkbox
|
||||
*ngFor="let option of objectKeys(userOptions)"
|
||||
color="primary"
|
||||
class="trace-box"
|
||||
[(ngModel)]="userOptions[option].enabled"
|
||||
(ngModelChange)="updateTree()"
|
||||
[matTooltip]="userOptions[option].tooltip ?? ''"
|
||||
>{{userOptions[option].name}}</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<property-groups
|
||||
*ngIf="itemIsSelected() && propertyGroups"
|
||||
class="property-groups"
|
||||
[item]="selectedFlickerItem"
|
||||
></property-groups>
|
||||
</div>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div class="properties-content">
|
||||
<h3 *ngIf="objectKeys(propertiesTree).length > 0 && isProtoDump" class="properties-title mat-subheading-2">Properties - Proto Dump</h3>
|
||||
|
||||
<div class="tree-wrapper">
|
||||
<tree-view
|
||||
*ngIf="objectKeys(propertiesTree).length > 0"
|
||||
@@ -67,12 +74,10 @@ import { PropertiesTreeNode, Terminal} from "viewers/common/ui_tree_utils";
|
||||
styles: [
|
||||
`
|
||||
.view-header {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-bottom: 1px solid var(--default-border);
|
||||
padding-bottom: 12px;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.title-filter {
|
||||
@@ -86,6 +91,7 @@ import { PropertiesTreeNode, Terminal} from "viewers/common/ui_tree_utils";
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
column-gap: 10px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
@@ -97,11 +103,12 @@ import { PropertiesTreeNode, Terminal} from "viewers/common/ui_tree_utils";
|
||||
}
|
||||
|
||||
.property-groups {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.tree-wrapper {
|
||||
overflow-y: auto
|
||||
overflow: auto
|
||||
}
|
||||
`,
|
||||
],
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
import {ComponentFixture, TestBed} from "@angular/core/testing";
|
||||
import { PropertyGroupsComponent } from "./property_groups.component";
|
||||
import { ComponentFixtureAutoDetect } from "@angular/core/testing";
|
||||
import { MatDividerModule } from "@angular/material/divider";
|
||||
import { TransformMatrixComponent } from "./transform_matrix.component";
|
||||
|
||||
describe("PropertyGroupsComponent", () => {
|
||||
@@ -25,6 +26,9 @@ describe("PropertyGroupsComponent", () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
MatDividerModule
|
||||
],
|
||||
providers: [
|
||||
{ provide: ComponentFixtureAutoDetect, useValue: true }
|
||||
],
|
||||
|
||||
@@ -34,6 +34,7 @@ import { Layer } from "common/trace/flickerlib/common";
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="group">
|
||||
<h3 class="group-header mat-subheading-2">Geometry</h3>
|
||||
<div class="left-column">
|
||||
@@ -72,6 +73,7 @@ import { Layer } from "common/trace/flickerlib/common";
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="group">
|
||||
<h3 class="group-header mat-subheading-2">Buffer</h3>
|
||||
<div class="left-column">
|
||||
@@ -112,6 +114,7 @@ import { Layer } from "common/trace/flickerlib/common";
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="group">
|
||||
<h3 class="group-header mat-subheading-2">Hierarchy</h3>
|
||||
<div class="left-column">
|
||||
@@ -135,6 +138,7 @@ import { Layer } from "common/trace/flickerlib/common";
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="group">
|
||||
<h3 class="group-header mat-subheading-2">Effects</h3>
|
||||
<div class="left-column">
|
||||
@@ -201,39 +205,42 @@ import { Layer } from "common/trace/flickerlib/common";
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="group">
|
||||
<h3 class="group-header mat-subheading-2">Input</h3>
|
||||
<div *ngIf="hasInputChannel()" class="left-column">
|
||||
<p class="property mat-body-2">To Display Transform:</p>
|
||||
<transform-matrix [transform]="item.inputTransform" [formatFloat]="formatFloat"></transform-matrix>
|
||||
<p class="mat-body-1">
|
||||
<span class="mat-body-2">Touchable Region:</span>
|
||||
&ngsp;
|
||||
{{ item.inputRegion }}
|
||||
</p>
|
||||
</div>
|
||||
<div *ngIf="hasInputChannel()" class="right-column">
|
||||
<p class="column-header mat-small">Config</p>
|
||||
<p class="mat-body-1">
|
||||
<span class="mat-body-2">Focusable:</span>
|
||||
&ngsp;
|
||||
{{ item.proto?.inputWindowInfo.focusable }}
|
||||
</p>
|
||||
<p class="mat-body-1">
|
||||
<span class="mat-body-2">Crop touch region with item:</span>
|
||||
&ngsp;
|
||||
{{
|
||||
item.proto?.inputWindowInfo.cropLayerId <= 0
|
||||
? "none"
|
||||
: item.proto?.inputWindowInfo.cropLayerId
|
||||
}}
|
||||
</p>
|
||||
<p class="mat-body-1">
|
||||
<span class="mat-body-2">Replace touch region with crop:</span>
|
||||
&ngsp;
|
||||
{{ item.proto?.inputWindowInfo.replaceTouchableRegionWithCrop }}
|
||||
</p>
|
||||
</div>
|
||||
<ng-container *ngIf="hasInputChannel()">
|
||||
<div class="left-column">
|
||||
<p class="property mat-body-2">To Display Transform:</p>
|
||||
<transform-matrix [transform]="item.inputTransform" [formatFloat]="formatFloat"></transform-matrix>
|
||||
<p class="mat-body-1">
|
||||
<span class="mat-body-2">Touchable Region:</span>
|
||||
&ngsp;
|
||||
{{ item.inputRegion }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="right-column">
|
||||
<p class="column-header mat-small">Config</p>
|
||||
<p class="mat-body-1">
|
||||
<span class="mat-body-2">Focusable:</span>
|
||||
&ngsp;
|
||||
{{ item.proto?.inputWindowInfo.focusable }}
|
||||
</p>
|
||||
<p class="mat-body-1">
|
||||
<span class="mat-body-2">Crop touch region with item:</span>
|
||||
&ngsp;
|
||||
{{
|
||||
item.proto?.inputWindowInfo.cropLayerId <= 0
|
||||
? "none"
|
||||
: item.proto?.inputWindowInfo.cropLayerId
|
||||
}}
|
||||
</p>
|
||||
<p class="mat-body-1">
|
||||
<span class="mat-body-2">Replace touch region with crop:</span>
|
||||
&ngsp;
|
||||
{{ item.proto?.inputWindowInfo.replaceTouchableRegionWithCrop }}
|
||||
</p>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div *ngIf="!hasInputChannel()" class="left-column">
|
||||
<p class="mat-body-1">
|
||||
<span class="mat-body-2">Input channel:</span>
|
||||
@@ -249,12 +256,11 @@ import { Layer } from "common/trace/flickerlib/common";
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid var(--default-border);
|
||||
}
|
||||
|
||||
.group-header {
|
||||
width: 80px;
|
||||
color: grey;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.left-column {
|
||||
@@ -270,7 +276,7 @@ import { Layer } from "common/trace/flickerlib/common";
|
||||
}
|
||||
|
||||
.column-header {
|
||||
color: grey;
|
||||
color: gray;
|
||||
}
|
||||
`
|
||||
],
|
||||
|
||||
@@ -304,7 +304,7 @@ export class CanvasGraphics {
|
||||
const circleMesh = this.makeLabelCircleMesh(rectMesh, rect);
|
||||
this.scene?.add(circleMesh);
|
||||
|
||||
const isGrey = !this.visibleView && !rect.isVisible;
|
||||
const isGray = !this.visibleView && !rect.isVisible;
|
||||
|
||||
let lineEndPos;
|
||||
const labelYSeparation = 0.5;
|
||||
@@ -320,14 +320,14 @@ export class CanvasGraphics {
|
||||
|
||||
const linePoints = [circleMesh.position, lineEndPos];
|
||||
const lineGeo = new THREE.BufferGeometry().setFromPoints(linePoints);
|
||||
const lineMaterial = new THREE.LineBasicMaterial({ color: isGrey ? 0x808080 : 0x000000 });
|
||||
const lineMaterial = new THREE.LineBasicMaterial({ color: isGray ? 0x808080 : 0x000000 });
|
||||
const line = new THREE.Line(lineGeo, lineMaterial);
|
||||
this.scene?.add(line);
|
||||
|
||||
this.drawLabelTextHtml(lineEndPos, rect, isGrey);
|
||||
this.drawLabelTextHtml(lineEndPos, rect, isGray);
|
||||
}
|
||||
|
||||
private drawLabelTextHtml(position: THREE.Vector3, rect: Rectangle, isGrey: boolean) {
|
||||
private drawLabelTextHtml(position: THREE.Vector3, rect: Rectangle, isGray: boolean) {
|
||||
// Add rectangle label
|
||||
const spanText: HTMLElement = document.createElement("span");
|
||||
spanText.innerText = this.shortenText(rect.label);
|
||||
@@ -347,8 +347,8 @@ export class CanvasGraphics {
|
||||
div.appendChild(spanPlaceholder);
|
||||
|
||||
div.style.marginTop = "5px";
|
||||
if (isGrey) {
|
||||
div.style.color = "grey";
|
||||
if (isGray) {
|
||||
div.style.color = "gray";
|
||||
}
|
||||
div.style.pointerEvents = "auto";
|
||||
div.style.cursor = "pointer";
|
||||
@@ -386,7 +386,7 @@ export class CanvasGraphics {
|
||||
const blue = ((183 - 44) * darkFactor + 44) / 255;
|
||||
color = new THREE.Color(red, green, blue);
|
||||
} else {
|
||||
// grey (darkness depends on z order)
|
||||
// gray (darkness depends on z order)
|
||||
const lower = 120;
|
||||
const upper = 220;
|
||||
const darkness = ((upper - lower) * darkFactor + lower) / 255;
|
||||
|
||||
@@ -18,7 +18,7 @@ import { Component, ViewChild } from "@angular/core";
|
||||
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
import { RectsComponent } from "viewers/components/rects/rects.component";
|
||||
import { MatCheckboxModule } from "@angular/material/checkbox";
|
||||
import { MatCardModule } from "@angular/material/card";
|
||||
import { MatDividerModule } from "@angular/material/divider";
|
||||
import { MatRadioModule } from "@angular/material/radio";
|
||||
import { MatSliderModule } from "@angular/material/slider";
|
||||
import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
|
||||
@@ -34,7 +34,7 @@ describe("RectsComponent", () => {
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatCheckboxModule,
|
||||
MatCardModule,
|
||||
MatDividerModule,
|
||||
MatSliderModule,
|
||||
MatRadioModule
|
||||
],
|
||||
|
||||
@@ -88,13 +88,19 @@ import { ViewerEvents } from "viewers/common/viewer_events";
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="rects-content">
|
||||
<div class="canvas-container">
|
||||
<canvas class="rects-canvas" (click)="onRectClick($event)" oncontextmenu="return false">
|
||||
</canvas>
|
||||
</div>
|
||||
<div *ngIf="displayIds.length > 1" class="tabs">
|
||||
<button color="primary" mat-raised-button *ngFor="let displayId of displayIds" (click)="changeDisplayId(displayId)">{{displayId}}</button>
|
||||
<div *ngIf="displayIds.length > 1" class="display-button-container">
|
||||
<button
|
||||
*ngFor="let displayId of displayIds"
|
||||
color="primary"
|
||||
mat-raised-button
|
||||
(click)="changeDisplayId(displayId)"
|
||||
>{{displayId}}</button>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
@@ -103,12 +109,12 @@ import { ViewerEvents } from "viewers/common/viewer_events";
|
||||
.view-controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-bottom: 1px solid var(--default-border);
|
||||
}
|
||||
.top-view-controls, .slider-view-controls {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
column-gap: 10px;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
@@ -126,8 +132,10 @@ import { ViewerEvents } from "viewers/common/viewer_events";
|
||||
top: 0;
|
||||
}
|
||||
.rects-content {
|
||||
height: 0;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.canvas-container {
|
||||
height: 100%;
|
||||
@@ -141,6 +149,12 @@ import { ViewerEvents } from "viewers/common/viewer_events";
|
||||
.rects-canvas {
|
||||
cursor: pointer;
|
||||
}
|
||||
.display-button-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
column-gap: 10px;
|
||||
}
|
||||
`
|
||||
]
|
||||
})
|
||||
|
||||
@@ -55,7 +55,6 @@ export const treeNodeDataViewStyles = `
|
||||
export const nodeInnerItemStyles = `
|
||||
.leaf-node-icon {content: ''; display: inline-block; margin-left: 40%; margin-top: 40%; height: 5px; width: 5px; border-radius: 50%;background-color: #9b9b9b;}
|
||||
.leaf-node-icon-wrapper, .description, .toggle-tree-btn, .expand-tree-btn, .pin-node-btn { position: relative; display: inline-block;}
|
||||
mat-icon {margin: 0}
|
||||
.pin-node-btn {padding: 0; transform: scale(0.7)}
|
||||
.description {align-items: center; flex: 1 1 auto; vertical-align: middle; word-break: break-all;}
|
||||
.leaf-node-icon-wrapper{padding-left: 6px; padding-right: 6px; min-height: 24px; width: 24px; position:relative; align-content: center; vertical-align: middle;}
|
||||
|
||||
@@ -17,8 +17,8 @@ import {ComponentFixture, TestBed} from "@angular/core/testing";
|
||||
import { ViewerInputMethodComponent } from "./viewer_input_method.component";
|
||||
import { HierarchyComponent } from "viewers/components/hierarchy.component";
|
||||
import { PropertiesComponent } from "viewers/components/properties.component";
|
||||
import { MatDividerModule } from "@angular/material/divider";
|
||||
import { MatIconModule } from "@angular/material/icon";
|
||||
import { MatCardModule } from "@angular/material/card";
|
||||
import { ComponentFixtureAutoDetect } from "@angular/core/testing";
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
|
||||
@@ -34,7 +34,7 @@ describe("ViewerInputMethodComponent", () => {
|
||||
],
|
||||
imports: [
|
||||
MatIconModule,
|
||||
MatCardModule
|
||||
MatDividerModule
|
||||
],
|
||||
declarations: [
|
||||
ViewerInputMethodComponent,
|
||||
|
||||
@@ -37,12 +37,19 @@ import { ImeUiData } from "viewers/common/ime_ui_data";
|
||||
[store]="store"
|
||||
[userOptions]="inputData?.hierarchyUserOptions ?? {}"
|
||||
></hierarchy-view>
|
||||
<ime-additional-properties
|
||||
*ngIf="inputData?.additionalProperties"
|
||||
class="ime-additional-properties-view"
|
||||
[additionalProperties]="inputData?.additionalProperties!"
|
||||
></ime-additional-properties>
|
||||
|
||||
<ng-container *ngIf="inputData?.additionalProperties">
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<ime-additional-properties
|
||||
class="ime-additional-properties"
|
||||
[additionalProperties]="inputData?.additionalProperties!"
|
||||
></ime-additional-properties>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<mat-divider [vertical]="true"></mat-divider>
|
||||
|
||||
<properties-view
|
||||
class="properties-view"
|
||||
[userOptions]="inputData?.propertiesUserOptions ?? {}"
|
||||
@@ -58,19 +65,12 @@ import { ImeUiData } from "viewers/common/ime_ui_data";
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.hierarchy-view, .ime-additional-properties-view {
|
||||
.hierarchy-view, .ime-additional-properties, .properties-view {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-top: 1px solid var(--default-border);
|
||||
border-right: 1px solid var(--default-border);
|
||||
}
|
||||
|
||||
.properties-view {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
border-top: 1px solid var(--default-border);
|
||||
overflow: auto;
|
||||
}
|
||||
`,
|
||||
]
|
||||
|
||||
@@ -65,6 +65,7 @@ import {ScreenRecordingTraceEntry} from "common/trace/screen_recording";
|
||||
|
||||
.drag-icon {
|
||||
float: left;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.button-minimize {
|
||||
|
||||
@@ -15,12 +15,11 @@
|
||||
*/
|
||||
import {ComponentFixture, TestBed} from "@angular/core/testing";
|
||||
import {ViewerSurfaceFlingerComponent} from "./viewer_surface_flinger.component";
|
||||
|
||||
import { HierarchyComponent } from "viewers/components/hierarchy.component";
|
||||
import { PropertiesComponent } from "viewers/components/properties.component";
|
||||
import { RectsComponent } from "viewers/components/rects/rects.component";
|
||||
import { MatIconModule } from "@angular/material/icon";
|
||||
import { MatCardModule } from "@angular/material/card";
|
||||
import { MatDividerModule } from "@angular/material/divider";
|
||||
import { ComponentFixtureAutoDetect } from "@angular/core/testing";
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
|
||||
@@ -36,7 +35,7 @@ describe("ViewerSurfaceFlingerComponent", () => {
|
||||
],
|
||||
imports: [
|
||||
MatIconModule,
|
||||
MatCardModule
|
||||
MatDividerModule
|
||||
],
|
||||
declarations: [
|
||||
ViewerSurfaceFlingerComponent,
|
||||
@@ -59,17 +58,17 @@ describe("ViewerSurfaceFlingerComponent", () => {
|
||||
});
|
||||
|
||||
it("creates rects view", () => {
|
||||
const rectsView = htmlElement.querySelector("#sf-rects-view");
|
||||
const rectsView = htmlElement.querySelector(".rects-view");
|
||||
expect(rectsView).toBeTruthy();
|
||||
});
|
||||
|
||||
it("creates hierarchy view", () => {
|
||||
const hierarchyView = htmlElement.querySelector("#sf-hierarchy-view");
|
||||
const hierarchyView = htmlElement.querySelector(".hierarchy-view");
|
||||
expect(hierarchyView).toBeTruthy();
|
||||
});
|
||||
|
||||
it("creates properties view", () => {
|
||||
const propertiesView = htmlElement.querySelector("#sf-properties-view");
|
||||
const propertiesView = htmlElement.querySelector(".properties-view");
|
||||
expect(propertiesView).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -27,7 +27,6 @@ import { PersistentStore } from "common/persistent_store";
|
||||
template: `
|
||||
<div class="card-grid">
|
||||
<rects-view
|
||||
id="sf-rects-view"
|
||||
class="rects-view"
|
||||
[rects]="inputData?.rects ?? []"
|
||||
[highlightedItems]="inputData?.highlightedItems ?? []"
|
||||
@@ -35,8 +34,8 @@ import { PersistentStore } from "common/persistent_store";
|
||||
[forceRefresh]="active"
|
||||
[hasVirtualDisplays]="inputData?.hasVirtualDisplays ?? false"
|
||||
></rects-view>
|
||||
<mat-divider [vertical]="true"></mat-divider>
|
||||
<hierarchy-view
|
||||
id="sf-hierarchy-view"
|
||||
class="hierarchy-view"
|
||||
[tree]="inputData?.tree ?? null"
|
||||
[dependencies]="inputData?.dependencies ?? []"
|
||||
@@ -45,8 +44,8 @@ import { PersistentStore } from "common/persistent_store";
|
||||
[store]="store"
|
||||
[userOptions]="inputData?.hierarchyUserOptions ?? {}"
|
||||
></hierarchy-view>
|
||||
<mat-divider [vertical]="true"></mat-divider>
|
||||
<properties-view
|
||||
id="sf-properties-view"
|
||||
class="properties-view"
|
||||
[userOptions]="inputData?.propertiesUserOptions ?? {}"
|
||||
[propertiesTree]="inputData?.propertiesTree ?? {}"
|
||||
@@ -58,30 +57,12 @@ import { PersistentStore } from "common/persistent_store";
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
.rects-view {
|
||||
.rects-view, .hierarchy-view, .properties-view {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-top: 1px solid var(--default-border);
|
||||
border-right: 1px solid var(--default-border);
|
||||
}
|
||||
|
||||
.hierarchy-view {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-top: 1px solid var(--default-border);
|
||||
border-right: 1px solid var(--default-border);
|
||||
}
|
||||
|
||||
.properties-view {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-top: 1px solid var(--default-border);
|
||||
overflow: auto;
|
||||
}
|
||||
`,
|
||||
]
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
import {ScrollingModule} from "@angular/cdk/scrolling";
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
import {ComponentFixture, ComponentFixtureAutoDetect, TestBed} from "@angular/core/testing";
|
||||
import {MatDividerModule} from "@angular/material/divider";
|
||||
import {UiData, UiDataEntry} from "./ui_data";
|
||||
import {PropertiesTreeGenerator} from "viewers/common/properties_tree_generator";
|
||||
import {ViewerTransactionsComponent} from "./viewer_transactions.component";
|
||||
@@ -31,6 +32,7 @@ describe("ViewerTransactionsComponent", () => {
|
||||
{ provide: ComponentFixtureAutoDetect, useValue: true }
|
||||
],
|
||||
imports: [
|
||||
MatDividerModule,
|
||||
ScrollingModule
|
||||
],
|
||||
declarations: [
|
||||
|
||||
@@ -111,6 +111,8 @@ import {UiData} from "./ui_data";
|
||||
</cdk-virtual-scroll-viewport>
|
||||
</div>
|
||||
|
||||
<mat-divider [vertical]="true"></mat-divider>
|
||||
|
||||
<div class="container-properties">
|
||||
<h3 class="properties-title mat-title">Properties - Proto Dump</h3>
|
||||
<tree-view
|
||||
@@ -127,16 +129,11 @@ import {UiData} from "./ui_data";
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
border-top: 1px solid var(--default-border);
|
||||
border-right: 1px solid var(--default-border);
|
||||
}
|
||||
|
||||
.container-properties {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
border-top: 1px solid var(--default-border);
|
||||
}
|
||||
|
||||
.entries .filters {
|
||||
|
||||
@@ -15,12 +15,11 @@
|
||||
*/
|
||||
import {ComponentFixture, TestBed} from "@angular/core/testing";
|
||||
import {ViewerWindowManagerComponent} from "./viewer_window_manager.component";
|
||||
|
||||
import { HierarchyComponent } from "viewers/components/hierarchy.component";
|
||||
import { PropertiesComponent } from "viewers/components/properties.component";
|
||||
import { RectsComponent } from "viewers/components/rects/rects.component";
|
||||
import { MatIconModule } from "@angular/material/icon";
|
||||
import { MatCardModule } from "@angular/material/card";
|
||||
import { MatDividerModule } from "@angular/material/divider";
|
||||
import { ComponentFixtureAutoDetect } from "@angular/core/testing";
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
|
||||
@@ -36,7 +35,7 @@ describe("ViewerWindowManagerComponent", () => {
|
||||
],
|
||||
imports: [
|
||||
MatIconModule,
|
||||
MatCardModule
|
||||
MatDividerModule
|
||||
],
|
||||
declarations: [
|
||||
ViewerWindowManagerComponent,
|
||||
@@ -59,17 +58,17 @@ describe("ViewerWindowManagerComponent", () => {
|
||||
});
|
||||
|
||||
it("creates rects view", () => {
|
||||
const rectsView = htmlElement.querySelector("#wm-rects-view");
|
||||
const rectsView = htmlElement.querySelector(".rects-view");
|
||||
expect(rectsView).toBeTruthy();
|
||||
});
|
||||
|
||||
it("creates hierarchy view", () => {
|
||||
const hierarchyView = htmlElement.querySelector("#wm-hierarchy-view");
|
||||
const hierarchyView = htmlElement.querySelector(".hierarchy-view");
|
||||
expect(hierarchyView).toBeTruthy();
|
||||
});
|
||||
|
||||
it("creates properties view", () => {
|
||||
const propertiesView = htmlElement.querySelector("#wm-properties-view");
|
||||
const propertiesView = htmlElement.querySelector(".properties-view");
|
||||
expect(propertiesView).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -27,15 +27,14 @@ import { PersistentStore } from "common/persistent_store";
|
||||
template: `
|
||||
<div class="card-grid">
|
||||
<rects-view
|
||||
id="wm-rects-view"
|
||||
class="rects-view"
|
||||
[rects]="inputData?.rects ?? []"
|
||||
[displayIds]="inputData?.displayIds ?? []"
|
||||
[highlightedItems]="inputData?.highlightedItems ?? []"
|
||||
[forceRefresh]="active"
|
||||
></rects-view>
|
||||
<mat-divider [vertical]="true"></mat-divider>
|
||||
<hierarchy-view
|
||||
id="wm-hierarchy-view"
|
||||
class="hierarchy-view"
|
||||
[tree]="inputData?.tree ?? null"
|
||||
[dependencies]="inputData?.dependencies ?? []"
|
||||
@@ -44,8 +43,8 @@ import { PersistentStore } from "common/persistent_store";
|
||||
[store]="store"
|
||||
[userOptions]="inputData?.hierarchyUserOptions ?? {}"
|
||||
></hierarchy-view>
|
||||
<mat-divider [vertical]="true"></mat-divider>
|
||||
<properties-view
|
||||
id="wm-properties-view"
|
||||
class="properties-view"
|
||||
[userOptions]="inputData?.propertiesUserOptions ?? {}"
|
||||
[propertiesTree]="inputData?.propertiesTree ?? {}"
|
||||
@@ -55,28 +54,12 @@ import { PersistentStore } from "common/persistent_store";
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
.rects-view {
|
||||
.rects-view, .hierarchy-view, .properties-view {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-top: 1px solid var(--default-border);
|
||||
border-right: 1px solid var(--default-border);
|
||||
}
|
||||
|
||||
.hierarchy-view {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-top: 1px solid var(--default-border);
|
||||
border-right: 1px solid var(--default-border);
|
||||
}
|
||||
|
||||
.properties-view {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
border-top: 1px solid var(--default-border);
|
||||
overflow: auto;
|
||||
}
|
||||
`,
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user