Merge changes I126a5f2f,I522d5d9f,I0eb35399,If3a79de6

* changes:
  Fix title (WinscopeNg => Winscope)
  Fix parsing of timeline's timestamp input
  Fix tslint errors
  Add tslint
This commit is contained in:
Kean Mariotti
2023-01-05 13:11:34 +00:00
committed by Android (Google) Code Review
119 changed files with 1222 additions and 767 deletions

View File

@@ -0,0 +1,138 @@
// Rules that don't require type information, Lint category.
// Enable non-strict mode to allow comments.
{
"rules": {
// The disabled rules below are google3 custom rules that need to be built
// and added to the project (see google3/javascript/typescript/tslint/rules/).
// If needed, it should be possible to build and run them in the Winscope npm
// environment as well. It is probably simpler and quicker to wait till
// Winscope is ported to google3 though.
//"angular-use-component-harnesses": true,
//"angular-output-is-readonly": true,
"array-type": [true, "array-simple"],
"arrow-return-shorthand": true,
"ban": [true,
["fit"],
["fpit"],
["fdescribe"],
["fpdescribe"],
["xit"],
["xpit"],
["xdescribe"],
["xpdescribe"],
["fitAsync"],
["xitAsync"],
["fitFakeAsync"],
["xitFakeAsync"],
{"name": ["it", "skip"]},
{"name": ["it", "only"]},
{"name": ["it", "async", "skip"]},
{"name": ["it", "async", "only"]},
{"name": ["pit", "skip"]},
{"name": ["pit", "only"]},
{"name": ["pit", "async", "skip"]},
{"name": ["pit", "async", "only"]},
{"name": ["describe", "skip"]},
{"name": ["describe", "only"]},
{"name": ["pdescribe", "skip"]},
{"name": ["pdescribe", "only"]},
{"name": ["describeWithDate", "skip"]},
{"name": ["describeWithDate", "only"]},
{"name": "parseInt", "message": "See http://go/tsstyle#type-coercion"},
{"name": "parseFloat", "message": "See http://go/tsstyle#type-coercion"},
{"name": "Array", "message": "See http://go/tsstyle#array-constructor"},
{"name": ["*", "innerText"], "message": "Use .textContent instead. http://go/typescript/patterns#browser-oddities"},
{"name": ["goog", "setTestOnly"], "message": "See http://go/tsstyle#tests"}
],
//"ban-as-never": true,
//"ban-implicit-undefined-default-parameters": true,
//"ban-jsdoc-enum-tag": true,
//"ban-malformed-import-paths": true,
//"ban-passing-async-function-to-describe": true,
//"ban-spy-returning-rejected-promise": true,
//"ban-strict-prop-init-comment": true,
// allowedSuppressions is a list of strings with no whitespace which, when
// found wrapped in parentheses immediately after the suppresion, will
// prevent this rule from triggering.
// For example: `// @ts-ignore(go/ts99upgrade) Some explanation.`
// Prefer using b/ bug links or go/ go links.
// To check if your suppression string is available in prod, use:
// cl-status/#/summary/tricorder.go-worker/[[SUBMITTED_CL_NUM]]
// Or, for CLs using the suppression, a go/startblock directive of:
// cl-status tricorder.go-worker contains cl/[[SUBMITTED_CL_NUM]] in prod
//"ban-ts-suppressions": [true, {
// "allowedSuppressions": [
// "b/249999919", // Node 18.x typings update
// "go/tsjs-aatm",
// "go/ts49upgrade",
// "go/jspb-ts-enums-fix",
// "KEEP_ME_LAST_TO_AVOID_NEEDING_TO_ADD_A_COMMA_TO_THE_LAST_ENTRY"
// ]
//}],
//"ban-tslint-disable": true,
"ban-types": [true,
["Object", "Use {} or 'object' instead. See http://go/ts-style#wrapper-types"],
["String", "Use 'string' instead."],
["Number", "Use 'number' instead."],
["Boolean", "Use 'boolean' instead."],
// Add tests in google3/javascript/typescript/tslint/test/googleConfig/ban_types.ts.lint
["AnyDuring(?!((ICentral|CelloJs|AngularIvy|Drive|1TF|AllAsUnknown|GoogPromiseThen|Search|DWE|JasmineApril2021|Assisted)Migration)).*",
"AnyDuringMigration is a quick-fix used during TypeScript migrations, and should be removed as soon as possible. See http://go/any_during_migration."]
],
// go/keep-sorted start
//"class-as-namespace": true,
"class-name": true,
"curly": [true, "ignore-same-line"],
//"decorator-placement": true,
//"discourage-angular-material-subpackage-imports": true,
//"enforce-comments-on-exported-symbols": true,
//"enforce-name-casing": true,
//"file-comment": true,
//"fix-trailing-comma-import-export": true,
"forin": true,
"interface-name": [true, "never-prefix"],
"interface-over-type-literal": true,
"jsdoc-format": true,
//"jsdoc-tags": true,
"label-position": true,
"member-access": [true, "no-public"],
"new-parens": true,
"no-angle-bracket-type-assertion": true,
//TODO (b/264508345): enable rule below after removeing 'any' types
//"no-any": true,
"no-conditional-assignment": [true, "allow-within-parenthesis"],
"no-construct": true,
"no-debugger": true,
"no-default-export": true,
"no-duplicate-switch-case": true,
//"no-inferrable-new-expression": true,
"no-namespace": [true, "allow-declarations"],
//"no-new-decorators": true,
//"no-quoted-property-signatures": true,
"no-reference": true,
"no-require-imports": true,
//"no-return-only-generics": true,
"no-string-throw": true,
//"no-undefined-type-alias": true,
//"no-unnecessary-escapes": true,
"no-unsafe-finally": true,
"no-unused-expression": [true, "allow-fast-null-checks"],
"no-unused-variable": true,
//"no-unused-wiz-injections": true,
"no-var-keyword": true,
"object-literal-shorthand": true,
"only-arrow-functions": [true, "allow-declarations", "allow-named-functions"],
"prefer-const": [true, {"destructuring": "all"}],
//"prefer-function-declaration": true,
//"prefer-type-annotation": true,
"radix": true,
"semicolon": [true, "always", "strict-bound-class-methods"],
"static-this": true,
"switch-default": true,
"triple-equals": [true, "allow-null-check"],
"unnecessary-constructor": true
//"well-formed-closure-message": true
// go/keep-sorted end
}
}

View File

@@ -79,6 +79,7 @@
"protractor": "^7.0.0",
"sass": "^1.56.1",
"sass-loader": "^13.1.0",
"tslint": "^6.1.3",
"webpack": "^5.74.0"
}
},
@@ -5162,6 +5163,15 @@
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
"node_modules/builtin-modules": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
"integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/builtins": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
@@ -6628,6 +6638,15 @@
"integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==",
"dev": true
},
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true,
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -16201,6 +16220,124 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
},
"node_modules/tslint": {
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz",
"integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==",
"deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.0.0",
"builtin-modules": "^1.1.1",
"chalk": "^2.3.0",
"commander": "^2.12.1",
"diff": "^4.0.1",
"glob": "^7.1.1",
"js-yaml": "^3.13.1",
"minimatch": "^3.0.4",
"mkdirp": "^0.5.3",
"resolve": "^1.3.2",
"semver": "^5.3.0",
"tslib": "^1.13.0",
"tsutils": "^2.29.0"
},
"bin": {
"tslint": "bin/tslint"
},
"engines": {
"node": ">=4.8.0"
},
"peerDependencies": {
"typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev"
}
},
"node_modules/tslint/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/tslint/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"node_modules/tslint/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/tslint/node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/tslint/node_modules/mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"dev": true,
"dependencies": {
"minimist": "^1.2.6"
},
"bin": {
"mkdirp": "bin/cmd.js"
}
},
"node_modules/tslint/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true,
"bin": {
"semver": "bin/semver"
}
},
"node_modules/tslint/node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
},
"node_modules/tslint/node_modules/tsutils": {
"version": "2.29.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
"dev": true,
"dependencies": {
"tslib": "^1.8.1"
},
"peerDependencies": {
"typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev"
}
},
"node_modules/tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
@@ -20968,6 +21105,12 @@
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
"builtin-modules": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
"integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==",
"dev": true
},
"builtins": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
@@ -22072,6 +22215,12 @@
"integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==",
"dev": true
},
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true
},
"dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -29201,6 +29350,98 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
},
"tslint": {
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz",
"integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"builtin-modules": "^1.1.1",
"chalk": "^2.3.0",
"commander": "^2.12.1",
"diff": "^4.0.1",
"glob": "^7.1.1",
"js-yaml": "^3.13.1",
"minimatch": "^3.0.4",
"mkdirp": "^0.5.3",
"resolve": "^1.3.2",
"semver": "^5.3.0",
"tslib": "^1.13.0",
"tsutils": "^2.29.0"
},
"dependencies": {
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"dev": true,
"requires": {
"minimist": "^1.2.6"
}
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
},
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
},
"tsutils": {
"version": "2.29.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
"dev": true,
"requires": {
"tslib": "^1.8.1"
}
}
}
},
"tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",

View File

@@ -4,8 +4,10 @@
"scripts": {
"format:check": "(ls *.js .*.js && find src/ -regextype egrep -regex '^.*(\\.ts|\\.js)$') |xargs npx prettier --check",
"format:fix": "(ls *.js .*.js && find src/ -regextype egrep -regex '^.*(\\.ts|\\.js)$') |xargs npx prettier --write",
"lint:check": "(ls *.js .*.js && find src/ -regextype egrep -regex '^.*(\\.ts|\\.js)$') |xargs npx eslint --format=unix",
"lint:fix": "(ls *.js .*.js && find src/ -regextype egrep -regex '^.*(\\.ts|\\.js)$') |xargs npx eslint --format=unix --fix",
"eslint:check": "(ls *.js .*.js && find src/ -regextype egrep -regex '^.*(\\.ts|\\.js)$') |xargs npx eslint --format=unix",
"eslint:fix": "(ls *.js .*.js && find src/ -regextype egrep -regex '^.*(\\.ts|\\.js)$') |xargs npx eslint --format=unix --fix",
"tslint:check": "find src/ -regextype egrep -regex '^.*\\.ts$' |xargs npx tslint -c google.tslint.json",
"tslint:fix": "find src/ -regextype egrep -regex '^.*\\.ts$' |xargs npx tslint -c google.tslint.json --fix",
"deps_graph:check_cycles": "count=$(npx madge --extensions ts,js src/ --circular 2>&1 | awk '/Found.*circular dependencies/ {print $3}'); test ${count:-0} -le 10",
"start": "webpack serve --config webpack.config.dev.js --open --hot --port 8080",
"start:remote_tool_mock": "webpack serve --config src/test/remote_tool_mock/webpack.config.js --open --hot --port 8081",
@@ -18,7 +20,7 @@
"test:unit": "jasmine dist/unit_test/bundle.js",
"test:component": "npx karma start",
"test:e2e": "npx protractor protractor.config.js",
"test:all": "npm run test:unit && npm run test:component && npm run test:e2e && npm run format:check && npm run lint:check && npm run deps_graph:check_cycles"
"test:all": "npm run test:unit && npm run test:component && npm run test:e2e && npm run format:check && npm run tslint:check && npm run eslint:check && npm run deps_graph:check_cycles"
},
"private": true,
"dependencies": {
@@ -93,6 +95,7 @@
"protractor": "^7.0.0",
"sass": "^1.56.1",
"sass-loader": "^13.1.0",
"tslint": "^6.1.3",
"webpack": "^5.74.0"
}
}

View File

@@ -138,13 +138,13 @@ export class AdbProxyComponent {
readonly downloadProxyUrl: string =
'https://android.googlesource.com/platform/development/+/master/tools/winscope/adb_proxy/winscope_proxy.py';
public restart() {
restart() {
this.addKey.emit(this.proxyKeyItem);
this.proxy.setState(this.states.CONNECTING);
this.proxyChange.emit(this.proxy);
}
public downloadFromAosp() {
downloadFromAosp() {
window.open(this.downloadProxyUrl, '_blank')?.focus();
}
}

View File

@@ -219,7 +219,7 @@ export class AppComponent implements TraceDataListener {
const storeDarkMode = this.store.get('dark-mode');
const prefersDarkQuery = window.matchMedia?.('(prefers-color-scheme: dark)');
this.setDarkMode(storeDarkMode != null ? storeDarkMode == 'true' : prefersDarkQuery.matches);
this.setDarkMode(storeDarkMode ? storeDarkMode === 'true' : prefersDarkQuery.matches);
if (!customElements.get('viewer-input-method')) {
customElements.define(
@@ -283,19 +283,19 @@ export class AppComponent implements TraceDataListener {
return this.timelineData.getScreenRecordingVideo();
}
public onTraceDataLoaded(viewers: Viewer[]) {
onTraceDataLoaded(viewers: Viewer[]) {
this.viewers = viewers;
this.dataLoaded = true;
this.changeDetectorRef.detectChanges();
}
public onTraceDataUnloaded() {
onTraceDataUnloaded() {
proxyClient.adbData = [];
this.dataLoaded = false;
this.changeDetectorRef.detectChanges();
}
public setDarkMode(enabled: boolean) {
setDarkMode(enabled: boolean) {
document.body.classList.toggle('dark-mode', enabled);
this.store.add('dark-mode', `${enabled}`);
this.isDarkModeOn = enabled;

View File

@@ -114,7 +114,7 @@ export class MatDrawer {
@Input() mode: 'push' | 'overlay' = 'overlay';
@Input() baseHeight = 0;
public getBaseHeight() {
getBaseHeight() {
return this.baseHeight;
}
}
@@ -158,7 +158,7 @@ export class MatDrawerContent /*extends MatDrawerContentBase*/ {
});
}
public setMargins(margins: {top: number | null; bottom: number | null}) {
setMargins(margins: {top: number | null; bottom: number | null}) {
this.contentMargins = margins;
}
}

View File

@@ -16,14 +16,19 @@
import {CanvasMouseHandler} from './canvas_mouse_handler';
export type padding = {left: number; top: number; right: number; bottom: number};
export interface Padding {
left: number;
top: number;
right: number;
bottom: number;
}
export interface CanvasDrawer {
draw(): void;
handler: CanvasMouseHandler;
canvas: HTMLCanvasElement;
ctx: CanvasRenderingContext2D;
padding: padding;
padding: Padding;
getXScale(): number;
getYScale(): number;
getWidth(): number;

View File

@@ -22,7 +22,7 @@ export type DropListener = DragListener;
export class CanvasMouseHandler {
// Ordered top most element to bottom most
private draggableObjects = new Array<DraggableCanvasObject>();
private draggableObjects: DraggableCanvasObject[] = [];
private draggingObject: DraggableCanvasObject | undefined = undefined;
private onDrag = new Map<DraggableCanvasObject, DragListener>();
@@ -47,7 +47,7 @@ export class CanvasMouseHandler {
});
}
public registerDraggableObject(
registerDraggableObject(
draggableObject: DraggableCanvasObject,
onDrag: DragListener,
onDrop: DropListener
@@ -56,7 +56,7 @@ export class CanvasMouseHandler {
this.onDrop.set(draggableObject, onDrop);
}
public notifyDrawnOnTop(draggableObject: DraggableCanvasObject) {
notifyDrawnOnTop(draggableObject: DraggableCanvasObject) {
const foundIndex = this.draggableObjects.indexOf(draggableObject);
if (foundIndex !== -1) {
this.draggableObjects.splice(foundIndex, 1);

View File

@@ -18,10 +18,10 @@ import {MathUtils} from 'three/src/Three';
import {Segment} from '../timeline/utils';
import {CanvasDrawer} from './canvas_drawer';
export type drawConfig = {
export interface DrawConfig {
fillStyle: string;
fill: boolean;
};
}
export class DraggableCanvasObject {
private draggingPosition: number | undefined;
@@ -30,7 +30,7 @@ export class DraggableCanvasObject {
private drawer: CanvasDrawer,
private positionGetter: () => number,
private definePathFunc: (ctx: CanvasRenderingContext2D, position: number) => void,
private drawConfig: drawConfig,
private drawConfig: DrawConfig,
private onDrag: (x: number) => void,
private onDrop: (x: number) => void,
private rangeGetter: () => Segment
@@ -58,11 +58,11 @@ export class DraggableCanvasObject {
return this.draggingPosition !== undefined ? this.draggingPosition : this.positionGetter();
}
public definePath(ctx: CanvasRenderingContext2D) {
definePath(ctx: CanvasRenderingContext2D) {
this.definePathFunc(ctx, this.position);
}
public draw(ctx: CanvasRenderingContext2D) {
draw(ctx: CanvasRenderingContext2D) {
this.doDraw(ctx);
this.drawer.handler.notifyDrawnOnTop(this);
}

View File

@@ -34,7 +34,7 @@ import {Connection} from 'trace_collection/connection';
import {ProxyState} from 'trace_collection/proxy_client';
import {ProxyConnection} from 'trace_collection/proxy_connection';
import {
configMap,
ConfigMap,
EnableConfiguration,
SelectionConfiguration,
traceConfigurations,
@@ -406,14 +406,14 @@ export class CollectTracesComponent implements OnInit, OnDestroy {
this.connect.proxy?.removeOnProxyChange(this.onProxyChange);
}
public onAddKey(key: string) {
onAddKey(key: string) {
if (this.connect.setProxyKey) {
this.connect.setProxyKey(key);
}
this.connect.restart();
}
public displayAdbProxyTab() {
displayAdbProxyTab() {
this.isAdbProxy = true;
this.connect = new ProxyConnection(
(newState) => this.changeDetectorRef.detectChanges(),
@@ -421,7 +421,7 @@ export class CollectTracesComponent implements OnInit, OnDestroy {
);
}
public displayWebAdbTab() {
displayWebAdbTab() {
this.isAdbProxy = false;
//TODO: change to WebAdbConnection
this.connect = new ProxyConnection(
@@ -430,7 +430,7 @@ export class CollectTracesComponent implements OnInit, OnDestroy {
);
}
public startTracing() {
startTracing() {
console.log('begin tracing');
this.tracingConfig.requestedTraces = this.requestedTraces();
const reqEnableConfig = this.requestedEnableConfig();
@@ -443,7 +443,7 @@ export class CollectTracesComponent implements OnInit, OnDestroy {
this.connect.startTrace(reqEnableConfig, reqSelectedSfConfig, reqSelectedWmConfig);
}
public async dumpState() {
async dumpState() {
console.log('begin dump');
this.tracingConfig.requestedDumps = this.requestedDumps();
const dumpSuccessful = await this.connect.dumpState();
@@ -454,13 +454,13 @@ export class CollectTracesComponent implements OnInit, OnDestroy {
}
}
public async endTrace() {
async endTrace() {
console.log('end tracing');
await this.connect.endTrace();
await this.loadFiles();
}
public tabClass(adbTab: boolean) {
tabClass(adbTab: boolean) {
let isActive: string;
if (adbTab) {
isActive = this.isAdbProxy ? 'active' : 'inactive';
@@ -475,7 +475,7 @@ export class CollectTracesComponent implements OnInit, OnDestroy {
}
private requestedTraces() {
const tracesFromCollection: Array<string> = [];
const tracesFromCollection: string[] = [];
const tracingConfig = this.tracingConfig.getTracingConfig();
const req = Object.keys(tracingConfig).filter((traceKey: string) => {
const traceConfig = tracingConfig[traceKey];
@@ -499,8 +499,8 @@ export class CollectTracesComponent implements OnInit, OnDestroy {
});
}
private requestedEnableConfig(): Array<string> {
const req: Array<string> = [];
private requestedEnableConfig(): string[] {
const req: string[] = [];
const tracingConfig = this.tracingConfig.getTracingConfig();
Object.keys(tracingConfig).forEach((traceKey: string) => {
const trace = tracingConfig[traceKey];
@@ -515,12 +515,12 @@ export class CollectTracesComponent implements OnInit, OnDestroy {
return req;
}
private requestedSelection(traceType: string): configMap | undefined {
private requestedSelection(traceType: string): ConfigMap | undefined {
const tracingConfig = this.tracingConfig.getTracingConfig();
if (!tracingConfig[traceType].run) {
return undefined;
}
const selected: configMap = {};
const selected: ConfigMap = {};
tracingConfig[traceType].config?.selectionConfigs.forEach((con: SelectionConfiguration) => {
selected[con.key] = con.value;
});

View File

@@ -49,7 +49,7 @@ export class ParserErrorSnackBarComponent {
) {}
static showIfNeeded(ngZone: NgZone, snackBar: MatSnackBar, errors: ParserError[]) {
const messages = this.convertErrorsToMessages(errors);
const messages = ParserErrorSnackBarComponent.convertErrorsToMessages(errors);
if (messages.length === 0) {
return;
@@ -67,7 +67,7 @@ export class ParserErrorSnackBarComponent {
private static convertErrorsToMessages(errors: ParserError[]): string[] {
const messages: string[] = [];
const groups = this.groupErrorsByType(errors);
const groups = ParserErrorSnackBarComponent.groupErrorsByType(errors);
for (const [type, groupedErrors] of groups) {
const CROP_THRESHOLD = 5;
@@ -75,11 +75,11 @@ export class ParserErrorSnackBarComponent {
const countCropped = groupedErrors.length - countUsed;
groupedErrors.slice(0, countUsed).forEach((error) => {
messages.push(this.convertErrorToMessage(error));
messages.push(ParserErrorSnackBarComponent.convertErrorToMessage(error));
});
if (countCropped > 0) {
messages.push(this.makeCroppedMessage(type, countCropped));
messages.push(ParserErrorSnackBarComponent.makeCroppedMessage(type, countCropped));
}
}

View File

@@ -30,7 +30,7 @@ export class MiniCanvasDrawerInput {
public timelineEntries: TimelineData
) {}
public transform(mapToRange: Segment): MiniCanvasDrawerData {
transform(mapToRange: Segment): MiniCanvasDrawerData {
const transformer = new Transformer(this.fullRange, mapToRange);
return new MiniCanvasDrawerData(
transformer.transform(this.selectedPosition),
@@ -74,13 +74,13 @@ export class Transformer {
this.toOffset = Math.round(this.toRange.from);
}
public transform(x: bigint): number {
transform(x: bigint): number {
return (
this.toOffset + (this.targetWidth * Number(x - this.fromOffset)) / Number(this.fromWidth)
);
}
public untransform(x: number): bigint {
untransform(x: number): bigint {
x = Math.round(x);
return (
this.fromOffset + (BigInt(x - this.toOffset) * this.fromWidth) / BigInt(this.targetWidth)
@@ -100,7 +100,7 @@ class MiniCanvasDrawerData {
public transformer: Transformer
) {}
public toOutput(): MiniCanvasDrawerOutput {
toOutput(): MiniCanvasDrawerOutput {
return new MiniCanvasDrawerOutput(this.transformer.untransform(this.selectedPosition), {
from: this.transformer.untransform(this.selection.from),
to: this.transformer.untransform(this.selection.to),
@@ -109,8 +109,8 @@ class MiniCanvasDrawerData {
}
export class MiniCanvasDrawer implements CanvasDrawer {
public ctx: CanvasRenderingContext2D;
public handler: CanvasMouseHandler;
ctx: CanvasRenderingContext2D;
handler: CanvasMouseHandler;
private activePointer: DraggableCanvasObject;
private leftFocusSectionSelector: DraggableCanvasObject;
@@ -120,19 +120,19 @@ export class MiniCanvasDrawer implements CanvasDrawer {
return this.getHeight() / 6;
}
public getXScale() {
getXScale() {
return this.ctx.getTransform().m11;
}
public getYScale() {
getYScale() {
return this.ctx.getTransform().m22;
}
public getWidth() {
getWidth() {
return this.canvas.width / this.getXScale();
}
public getHeight() {
getHeight() {
return this.canvas.height / this.getYScale();
}
@@ -298,7 +298,7 @@ export class MiniCanvasDrawer implements CanvasDrawer {
return this.getHeight() - this.padding.top - this.padding.bottom;
}
public draw() {
draw() {
this.ctx.clearRect(0, 0, this.getWidth(), this.getHeight());
this.drawSelectionBackground();
@@ -387,7 +387,7 @@ export class MiniCanvasDrawer implements CanvasDrawer {
const spacing = (this.getWidth() - barSets * barsInSetWidth - edgeBarWidth) / bars;
let start = edgeBarWidth + spacing;
for (let i = 1; i < bars; i++) {
if (i % 10 == 0) {
if (i % 10 === 0) {
// Draw boldbar
this.ctx.fillStyle = Color.GUIDE_BAR;
this.ctx.fillRect(

View File

@@ -113,7 +113,7 @@ export class MiniTimelineComponent {
}
private getTimelinesToShow() {
const timelines = new Map<TraceType, bigint[]>();
const timelines = new Map<TraceType, Array<bigint>>();
for (const type of this.selectedTraces) {
timelines.set(
type,

View File

@@ -48,7 +48,7 @@ export class SingleTimelineComponent {
@Input() color = '#AF5CF7';
@Input() start!: bigint;
@Input() end!: bigint;
@Input() entries!: bigint[];
@Input() entries!: Array<bigint>;
@Output() onTimestampChanged = new EventEmitter<bigint>();
@@ -74,7 +74,7 @@ export class SingleTimelineComponent {
}
ngOnInit() {
if (this.start == undefined || this.end == undefined || this.entries == undefined) {
if (this.start === undefined || this.end === undefined || this.entries === undefined) {
throw Error('Not all required inputs have been set');
}
}
@@ -85,7 +85,7 @@ export class SingleTimelineComponent {
this.initializeCanvas();
}
public initializeCanvas() {
initializeCanvas() {
// Reset any size before computing new size to avoid it interfering with size computations
this.canvas.width = 0;
this.canvas.height = 0;
@@ -96,7 +96,9 @@ export class SingleTimelineComponent {
const width = this.wrapperRef.nativeElement.offsetWidth;
const height =
this.wrapperRef.nativeElement.offsetHeight -
// tslint:disable-next-line:ban
parseFloat(computedStyle.paddingTop) -
// tslint:disable-next-line:ban
parseFloat(computedStyle.paddingBottom);
const HiPPIwidth = window.devicePixelRatio * width;
@@ -135,7 +137,7 @@ export class SingleTimelineComponent {
}
private handleMouseOut(e: MouseEvent) {
if (this.hoveringEntry != null) {
if (this.hoveringEntry !== null) {
// If null there is no current hover effect so no need to clear
this.redraw();
}
@@ -162,7 +164,7 @@ export class SingleTimelineComponent {
private drawEntryHover(mouseX: number, mouseY: number) {
const currentHoverEntry = this.getEntryAt(mouseX, mouseY);
if (this.hoveringEntry == currentHoverEntry) {
if (this.hoveringEntry === currentHoverEntry) {
return;
}
@@ -212,7 +214,7 @@ export class SingleTimelineComponent {
}
private updateCursor(mouseX: number, mouseY: number) {
if (this.getEntryAt(mouseX, mouseY) != null) {
if (this.getEntryAt(mouseX, mouseY) !== null) {
this.canvas.style.cursor = 'pointer';
}
this.canvas.style.cursor = 'auto';
@@ -227,7 +229,7 @@ export class SingleTimelineComponent {
const clickedEntry = this.getEntryAt(mouseX, mouseY);
if (clickedEntry != null) {
if (this.selected != clickedEntry) {
if (this.selected !== clickedEntry) {
this.selected = clickedEntry;
this.redraw();
this.onTimestampChanged.emit(clickedEntry);

View File

@@ -30,6 +30,7 @@ import {FormControl, FormGroup, Validators} from '@angular/forms';
import {DomSanitizer, SafeUrl} from '@angular/platform-browser';
import {TimelineData} from 'app/timeline_data';
import {TRACE_INFO} from 'app/trace_info';
import {StringUtils} from 'common/string_utils';
import {TimeUtils} from 'common/time_utils';
import {TimestampChangeListener} from 'interfaces/timestamp_change_listener';
import {ElapsedTimestamp, RealTimestamp, Timestamp, TimestampType} from 'trace/timestamp';
@@ -287,8 +288,8 @@ import {MiniTimelineComponent} from './mini_timeline_component';
],
})
export class TimelineComponent implements TimestampChangeListener {
public readonly TOGGLE_BUTTON_CLASS: string = 'button-toggle-expansion';
public readonly MAX_SELECTED_TRACES = 3;
readonly TOGGLE_BUTTON_CLASS: string = 'button-toggle-expansion';
readonly MAX_SELECTED_TRACES = 3;
@Input() set activeViewTraceTypes(types: TraceType[] | undefined) {
if (!types) {
@@ -312,7 +313,7 @@ export class TimelineComponent implements TimestampChangeListener {
this.selectedTracesFormControl.setValue(this.selectedTraces);
}
public internalActiveTrace: TraceType | undefined = undefined;
internalActiveTrace: TraceType | undefined = undefined;
@Input() timelineData!: TimelineData;
@Input() availableTraces: TraceType[] = [];
@@ -458,15 +459,10 @@ export class TimelineComponent implements TimestampChangeListener {
@HostListener('document:keydown', ['$event'])
handleKeyboardEvent(event: KeyboardEvent) {
switch (event.key) {
case 'ArrowLeft': {
this.moveToPreviousEntry();
break;
}
case 'ArrowRight': {
this.moveToNextEntry();
break;
}
if (event.key === 'ArrowLeft') {
this.moveToPreviousEntry();
} else if (event.key === 'ArrowRight') {
this.moveToNextEntry();
}
}
@@ -531,7 +527,10 @@ export class TimelineComponent implements TimestampChangeListener {
}
const target = event.target as HTMLInputElement;
const timestamp = new Timestamp(this.timelineData.getTimestampType()!, BigInt(target.value));
const timestamp = new Timestamp(
this.timelineData.getTimestampType()!,
StringUtils.parseBigIntStrippingUnit(target.value)
);
this.timelineData.setCurrentTimestamp(timestamp);
this.updateTimeInputValuesToCurrentTimestamp();
}

View File

@@ -86,7 +86,7 @@ describe('TimelineComponent', () => {
[
{
traceType: TraceType.SURFACE_FLINGER,
timestamps: timestamps,
timestamps,
},
],
undefined
@@ -117,7 +117,7 @@ describe('TimelineComponent', () => {
[
{
traceType: TraceType.SURFACE_FLINGER,
timestamps: timestamps,
timestamps,
},
],
undefined

View File

@@ -16,6 +16,12 @@
import {TraceType} from 'trace/trace_type';
export type Segment = {from: number; to: number};
export type BigIntSegment = {from: bigint; to: bigint};
export type TimelineData = Map<TraceType, bigint[]>;
export interface Segment {
from: number;
to: number;
}
export interface BigIntSegment {
from: bigint;
to: bigint;
}
export type TimelineData = Map<TraceType, Array<bigint>>;

View File

@@ -97,8 +97,8 @@ export class TraceConfigComponent {
objectKeys = Object.keys;
@Input() traces!: TraceConfigurationMap;
public advancedConfigTraces() {
const advancedConfigs: Array<string> = [];
advancedConfigTraces() {
const advancedConfigs: string[] = [];
Object.keys(this.traces).forEach((traceKey: string) => {
if (this.traces[traceKey].config) {
advancedConfigs.push(traceKey);
@@ -107,7 +107,7 @@ export class TraceConfigComponent {
return advancedConfigs;
}
public traceEnableConfigs(trace: TraceConfiguration): Array<EnableConfiguration> {
traceEnableConfigs(trace: TraceConfiguration): EnableConfiguration[] {
if (trace.config) {
return trace.config.enableConfigs;
} else {
@@ -115,7 +115,7 @@ export class TraceConfigComponent {
}
}
public traceSelectionConfigs(trace: TraceConfiguration): Array<SelectionConfiguration> {
traceSelectionConfigs(trace: TraceConfiguration): SelectionConfiguration[] {
if (trace.config) {
return trace.config.selectionConfigs;
} else {
@@ -123,18 +123,18 @@ export class TraceConfigComponent {
}
}
public someTraces(trace: TraceConfiguration): boolean {
someTraces(trace: TraceConfiguration): boolean {
return this.traceEnableConfigs(trace).filter((trace) => trace.enabled).length > 0 && !trace.run;
}
public changeRunTrace(run: boolean, trace: TraceConfiguration): void {
changeRunTrace(run: boolean, trace: TraceConfiguration): void {
trace.run = run;
if (trace.isTraceCollection) {
this.traceEnableConfigs(trace).forEach((c: EnableConfiguration) => (c.enabled = run));
}
}
public changeTraceCollectionConfig(trace: TraceConfiguration): void {
changeTraceCollectionConfig(trace: TraceConfiguration): void {
if (trace.isTraceCollection) {
trace.run = this.traceEnableConfigs(trace).every((c: EnableConfiguration) => c.enabled);
}

View File

@@ -101,7 +101,7 @@ export class TraceViewComponent {
private elementRef: ElementRef;
public tabs: Tab[] = [];
tabs: Tab[] = [];
private currentActiveTab: undefined | Tab;
constructor(@Inject(ElementRef) elementRef: ElementRef) {
@@ -113,7 +113,7 @@ export class TraceViewComponent {
this.renderViewsOverlay();
}
public onTabClick(tab: Tab) {
onTabClick(tab: Tab) {
this.showTab(tab);
}
@@ -189,7 +189,7 @@ export class TraceViewComponent {
this.activeViewChanged.emit(tab);
}
public isCurrentActiveTab(tab: Tab) {
isCurrentActiveTab(tab: Tab) {
return tab === this.currentActiveTab;
}
}

View File

@@ -59,7 +59,7 @@ describe('TraceViewComponent', () => {
const getVisibleTabContents = () => {
const contents: HTMLElement[] = [];
htmlElement.querySelectorAll('.trace-view-content div').forEach((content) => {
if ((content as HTMLElement).style.display != 'none') {
if ((content as HTMLElement).style.display !== 'none') {
contents.push(content as HTMLElement);
}
});

View File

@@ -186,42 +186,42 @@ export class UploadTracesComponent implements FilesDownloadListener {
this.traceData.clear();
}
public onFilesDownloadStart() {
onFilesDownloadStart() {
this.isLoadingFiles = true;
this.progressMessage = 'Downloading files...';
this.progressPercentage = undefined;
this.changeDetectorRef.detectChanges();
}
public async onFilesDownloaded(files: File[]) {
async onFilesDownloaded(files: File[]) {
await this.processFiles(files);
}
public async onInputFiles(event: Event) {
async onInputFiles(event: Event) {
const files = this.getInputFiles(event);
await this.processFiles(files);
}
public onViewTracesButtonClick() {
onViewTracesButtonClick() {
this.traceDataLoaded.emit();
}
public onClearButtonClick() {
onClearButtonClick() {
this.traceData.clear();
this.changeDetectorRef.detectChanges();
}
public onFileDragIn(e: DragEvent) {
onFileDragIn(e: DragEvent) {
e.preventDefault();
e.stopPropagation();
}
public onFileDragOut(e: DragEvent) {
onFileDragOut(e: DragEvent) {
e.preventDefault();
e.stopPropagation();
}
public async onHandleFileDrop(e: DragEvent) {
async onHandleFileDrop(e: DragEvent) {
e.preventDefault();
e.stopPropagation();
const droppedFiles = e.dataTransfer?.files;
@@ -229,7 +229,7 @@ export class UploadTracesComponent implements FilesDownloadListener {
await this.processFiles(Array.from(droppedFiles));
}
public onRemoveTrace(event: MouseEvent, trace: Trace) {
onRemoveTrace(event: MouseEvent, trace: Trace) {
event.preventDefault();
event.stopPropagation();
this.traceData.removeTrace(trace.type);

View File

@@ -93,29 +93,29 @@ export class Mediator {
);
}
public setUploadTracesComponent(
setUploadTracesComponent(
uploadTracesComponent: UploadTracesComponentDependencyInversion | undefined
) {
this.uploadTracesComponent = uploadTracesComponent;
}
public setTimelineComponent(timelineComponent: TimelineComponentDependencyInversion | undefined) {
setTimelineComponent(timelineComponent: TimelineComponentDependencyInversion | undefined) {
this.timelineComponent = timelineComponent;
}
public onWinscopeInitialized() {
onWinscopeInitialized() {
this.abtChromeExtensionProtocol.run();
}
public onWinscopeUploadNew() {
onWinscopeUploadNew() {
this.resetAppToInitialState();
}
public onWinscopeTraceDataLoaded() {
onWinscopeTraceDataLoaded() {
this.processTraceData();
}
public onWinscopeCurrentTimestampChanged(timestamp: Timestamp | undefined) {
onWinscopeCurrentTimestampChanged(timestamp: Timestamp | undefined) {
this.executeIgnoringRecursiveTimestampNotifications(() => {
const entries = this.traceData.getTraceEntries(timestamp);
this.viewers.forEach((viewer) => {

View File

@@ -23,8 +23,14 @@ import {TraceType} from 'trace/trace_type';
import {Timeline} from './trace_data';
export type TimestampCallbackType = (timestamp: Timestamp | undefined) => void;
export type TimeRange = {from: Timestamp; to: Timestamp};
type TimestampWithIndex = {index: number; timestamp: Timestamp};
export interface TimeRange {
from: Timestamp;
to: Timestamp;
}
interface TimestampWithIndex {
index: number;
timestamp: Timestamp;
}
export class TimelineData {
private timelines = new Map<TraceType, Timestamp[]>();
@@ -35,13 +41,13 @@ export class TimelineData {
private activeViewTraceTypes: TraceType[] = []; // dependencies of current active view
private onCurrentTimestampChanged: TimestampCallbackType = FunctionUtils.DO_NOTHING;
public initialize(timelines: Timeline[], screenRecordingVideo: Blob | undefined) {
initialize(timelines: Timeline[], screenRecordingVideo: Blob | undefined) {
this.clear();
this.screenRecordingVideo = screenRecordingVideo;
const allTimestamps = timelines.flatMap((timeline) => timeline.timestamps);
if (allTimestamps.some((timestamp) => timestamp.getType() != allTimestamps[0].getType())) {
if (allTimestamps.some((timestamp) => timestamp.getType() !== allTimestamps[0].getType())) {
throw Error('Added timeline has inconsistent timestamps.');
}
@@ -70,7 +76,7 @@ export class TimelineData {
return this.getFirstTimestamp();
}
public setCurrentTimestamp(timestamp: Timestamp | undefined) {
setCurrentTimestamp(timestamp: Timestamp | undefined) {
if (!this.hasTimestamps()) {
console.warn('Attempted to set timestamp on traces with no timestamps/entries...');
return;
@@ -90,17 +96,17 @@ export class TimelineData {
});
}
public setActiveViewTraceTypes(types: TraceType[]) {
setActiveViewTraceTypes(types: TraceType[]) {
this.applyOperationAndNotifyIfCurrentTimestampChanged(() => {
this.activeViewTraceTypes = types;
});
}
public getTimestampType(): TimestampType | undefined {
getTimestampType(): TimestampType | undefined {
return this.timestampType;
}
public getFullRange(): TimeRange {
getFullRange(): TimeRange {
if (!this.hasTimestamps()) {
throw Error('Trying to get full range when there are no timestamps');
}
@@ -110,7 +116,7 @@ export class TimelineData {
};
}
public getSelectionRange(): TimeRange {
getSelectionRange(): TimeRange {
if (this.explicitlySetSelection === undefined) {
return this.getFullRange();
} else {
@@ -118,19 +124,19 @@ export class TimelineData {
}
}
public setSelectionRange(selection: TimeRange) {
setSelectionRange(selection: TimeRange) {
this.explicitlySetSelection = selection;
}
public getTimelines(): Map<TraceType, Timestamp[]> {
getTimelines(): Map<TraceType, Timestamp[]> {
return this.timelines;
}
public getScreenRecordingVideo(): Blob | undefined {
getScreenRecordingVideo(): Blob | undefined {
return this.screenRecordingVideo;
}
public searchCorrespondingScreenRecordingTimeSeconds(timestamp: Timestamp): number | undefined {
searchCorrespondingScreenRecordingTimeSeconds(timestamp: Timestamp): number | undefined {
const timestamps = this.timelines.get(TraceType.SCREEN_RECORDING);
if (!timestamps) {
return undefined;
@@ -149,19 +155,19 @@ export class TimelineData {
return ScreenRecordingUtils.timestampToVideoTimeSeconds(firstTimestamp, correspondingTimestamp);
}
public hasTimestamps(): boolean {
hasTimestamps(): boolean {
return Array.from(this.timelines.values()).some((timestamps) => timestamps.length > 0);
}
public hasMoreThanOneDistinctTimestamp(): boolean {
hasMoreThanOneDistinctTimestamp(): boolean {
return this.hasTimestamps() && this.getFirstTimestamp() !== this.getLastTimestamp();
}
public getCurrentTimestampFor(type: TraceType): Timestamp | undefined {
getCurrentTimestampFor(type: TraceType): Timestamp | undefined {
return this.searchCorrespondingTimestampFor(type, this.getCurrentTimestamp())?.timestamp;
}
public getPreviousTimestampFor(type: TraceType): Timestamp | undefined {
getPreviousTimestampFor(type: TraceType): Timestamp | undefined {
const currentIndex = this.searchCorrespondingTimestampFor(
type,
this.getCurrentTimestamp()
@@ -186,11 +192,11 @@ export class TimelineData {
return this.timelines.get(type)?.[previousIndex];
}
public getNextTimestampFor(type: TraceType): Timestamp | undefined {
getNextTimestampFor(type: TraceType): Timestamp | undefined {
const currentIndex =
this.searchCorrespondingTimestampFor(type, this.getCurrentTimestamp())?.index ?? -1;
if (this.timelines.get(type)?.length == 0 ?? true) {
if (this.timelines.get(type)?.length === 0 ?? true) {
throw Error(`Missing active timestamp for trace type ${type}`);
}
@@ -206,21 +212,21 @@ export class TimelineData {
return timestamps[nextIndex];
}
public moveToPreviousTimestampFor(type: TraceType) {
moveToPreviousTimestampFor(type: TraceType) {
const prevTimestamp = this.getPreviousTimestampFor(type);
if (prevTimestamp !== undefined) {
this.setCurrentTimestamp(prevTimestamp);
}
}
public moveToNextTimestampFor(type: TraceType) {
moveToNextTimestampFor(type: TraceType) {
const nextTimestamp = this.getNextTimestampFor(type);
if (nextTimestamp !== undefined) {
this.setCurrentTimestamp(nextTimestamp);
}
}
public clear() {
clear() {
this.applyOperationAndNotifyIfCurrentTimestampChanged(() => {
this.timelines.clear();
this.explicitlySetTimestamp = undefined;

View File

@@ -33,7 +33,7 @@ class TraceData {
private parsers: Parser[] = [];
private commonTimestampType?: TimestampType;
public async loadTraces(
async loadTraces(
traceFiles: TraceFile[],
onLoadProgressUpdate: OnProgressUpdateType = FunctionUtils.DO_NOTHING
): Promise<ParserError[]> {
@@ -45,15 +45,15 @@ class TraceData {
return parserErrors;
}
public removeTrace(type: TraceType) {
removeTrace(type: TraceType) {
this.parsers = this.parsers.filter((parser) => parser.getTraceType() !== type);
}
public getLoadedTraces(): Trace[] {
getLoadedTraces(): Trace[] {
return this.parsers.map((parser: Parser) => parser.getTrace());
}
public getTraceEntries(timestamp: Timestamp | undefined): Map<TraceType, any> {
getTraceEntries(timestamp: Timestamp | undefined): Map<TraceType, any> {
const traceEntries: Map<TraceType, any> = new Map<TraceType, any>();
if (!timestamp) {
@@ -86,19 +86,19 @@ class TraceData {
return traceEntries;
}
public getTimelines(): Timeline[] {
getTimelines(): Timeline[] {
const timelines = this.parsers.map((parser): Timeline => {
const timestamps = parser.getTimestamps(this.getCommonTimestampType());
if (timestamps === undefined) {
throw Error('Failed to get timestamps from parser');
}
return {traceType: parser.getTraceType(), timestamps: timestamps};
return {traceType: parser.getTraceType(), timestamps};
});
return timelines;
}
public getScreenRecordingVideo(): undefined | Blob {
getScreenRecordingVideo(): undefined | Blob {
const parser = this.parsers.find(
(parser) => parser.getTraceType() === TraceType.SCREEN_RECORDING
);
@@ -114,7 +114,7 @@ class TraceData {
return (parser.getTraceEntry(timestamps[0]) as ScreenRecordingTraceEntry)?.videoData;
}
public clear() {
clear() {
this.parserFactory = new ParserFactory();
this.parsers = [];
this.commonTimestampType = undefined;

View File

@@ -13,11 +13,11 @@ const ACCESSIBILITY_ICON = 'filter_none';
const TAG_ICON = 'details';
const TRACE_ERROR_ICON = 'warning';
type iconMap = {
interface IconMap {
[key: number]: string;
};
}
export const TRACE_ICONS: iconMap = {
export const TRACE_ICONS: IconMap = {
[TraceType.ACCESSIBILITY]: ACCESSIBILITY_ICON,
[TraceType.WINDOW_MANAGER]: WINDOW_MANAGER_ICON,
[TraceType.SURFACE_FLINGER]: SURFACE_FLINGER_ICON,

View File

@@ -29,15 +29,15 @@ const ACCESSIBILITY_ICON = 'accessibility_new';
const TAG_ICON = 'details';
const TRACE_ERROR_ICON = 'warning';
type traceInfoMap = {
interface TraceInfoMap {
[key: number]: {
name: string;
icon: string;
color: string;
};
};
}
export const TRACE_INFO: traceInfoMap = {
export const TRACE_INFO: TraceInfoMap = {
[TraceType.ACCESSIBILITY]: {
name: 'Accessibility',
icon: ACCESSIBILITY_ICON,

View File

@@ -31,7 +31,7 @@ class ArrayUtils {
}
for (let i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
if (a[i] !== b[i]) {
return false;
}
}
@@ -47,7 +47,7 @@ class ArrayUtils {
let match = true;
for (let j = 0; j < subarray.length; ++j) {
if (array[i + j] != subarray[j]) {
if (array[i + j] !== subarray[j]) {
match = false;
break;
}
@@ -62,7 +62,7 @@ class ArrayUtils {
}
static binarySearchLowerOrEqual<T>(values: T[] | TypedArray, target: T): number | undefined {
if (values.length == 0) {
if (values.length === 0) {
return undefined;
}

View File

@@ -61,7 +61,7 @@ class FileUtils {
// Ignore directories
continue;
} else {
const name = this.removeDirFromFileName(filename);
const name = FileUtils.removeDirFromFileName(filename);
const fileBlob = await file.async('blob');
const unzippedFile = new File([fileBlob], name);
unzippedFiles.push(unzippedFile);
@@ -96,7 +96,7 @@ class FileUtils {
}
static isZipFile(file: File) {
return this.getFileExtension(file) === 'zip';
return FileUtils.getFileExtension(file) === 'zip';
}
}

View File

@@ -14,11 +14,11 @@
* limitations under the License.
*/
export class PersistentStore {
public add(key: string, value: string) {
add(key: string, value: string) {
localStorage.setItem(key, value);
}
public get(key: string) {
get(key: string) {
return localStorage.getItem(key);
}
}

View File

@@ -14,38 +14,30 @@
* limitations under the License.
*/
export type StoreObject =
| {[key: string | number]: StoreObject | string | boolean | undefined}
| StoreObject[]
| string[]
| boolean[];
export class PersistentStoreProxy {
public static new<T extends StoreObject>(key: string, defaultState: T, storage: Storage): T {
static new<T extends object>(key: string, defaultState: T, storage: Storage): T {
const storedState = JSON.parse(storage.getItem(key) ?? '{}');
const currentState = mergeDeep({}, deepClone(defaultState));
const currentState = mergeDeep({}, structuredClone(defaultState));
mergeDeepKeepingStructure(currentState, storedState);
return wrapWithPersistentStoreProxy<T>(key, currentState, storage);
return wrapWithPersistentStoreProxy(key, currentState, storage) as T;
}
}
function wrapWithPersistentStoreProxy<T extends StoreObject>(
function wrapWithPersistentStoreProxy(
storeKey: string,
object: T,
object: object,
storage: Storage,
baseObject: T = object
): T {
baseObject: object = object
): object {
const updatableProps: string[] = [];
let key: number | string;
for (key in object) {
const value = object[key];
for (const [key, value] of Object.entries(object)) {
if (typeof value === 'string' || typeof value === 'boolean' || value === undefined) {
if (!Array.isArray(object)) {
updatableProps.push(key);
}
} else {
object[key] = wrapWithPersistentStoreProxy(storeKey, value, storage, baseObject);
(object as any)[key] = wrapWithPersistentStoreProxy(storeKey, value, storage, baseObject);
}
}
@@ -60,7 +52,7 @@ function wrapWithPersistentStoreProxy<T extends StoreObject>(
return true;
}
if (!Array.isArray(target) && updatableProps.includes(prop)) {
target[prop] = newValue;
(target as any)[prop] = newValue;
storage.setItem(storeKey, JSON.stringify(baseObject));
return true;
}
@@ -122,7 +114,3 @@ function mergeDeep(target: any, ...sources: any): any {
return mergeDeep(target, ...sources);
}
function deepClone(obj: StoreObject): StoreObject {
return JSON.parse(JSON.stringify(obj));
}

View File

@@ -15,7 +15,7 @@
*/
import {MockStorage} from 'test/unit/mock_storage';
import {PersistentStoreProxy, StoreObject} from './persistent_store_proxy';
import {PersistentStoreProxy} from './persistent_store_proxy';
describe('PersistentStoreObject', () => {
it('uses defaults when no store is available', () => {
@@ -85,14 +85,14 @@ describe('PersistentStoreObject', () => {
it("can't update non leaf configs", () => {
const mockStorage = new MockStorage();
const defaultValues: StoreObject = {
const defaultValues = {
key1: 'value',
key2: {
key3: true,
},
};
const storeObject = PersistentStoreProxy.new('storeKey', defaultValues, mockStorage);
expect(() => (storeObject['key2'] = false)).toThrow();
expect(() => (storeObject['key2'] = {key3: false})).toThrow();
});
it('can get nested configs', () => {

View File

@@ -0,0 +1,27 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class StringUtils {
static parseBigIntStrippingUnit(s: string): bigint {
const match = s.match(/^\s*(-?\d+)\D*.*$/);
if (!match) {
throw new Error(`Cannot parse '${s}' as bigint`);
}
return BigInt(match[1]);
}
}
export {StringUtils};

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {StringUtils} from './string_utils';
describe('StringUtils', () => {
it('parses bigint', () => {
expect(StringUtils.parseBigIntStrippingUnit('-10')).toEqual(-10n);
expect(StringUtils.parseBigIntStrippingUnit('-10 unit')).toEqual(-10n);
expect(StringUtils.parseBigIntStrippingUnit('-10unit')).toEqual(-10n);
expect(StringUtils.parseBigIntStrippingUnit(' -10 unit ')).toEqual(-10n);
expect(StringUtils.parseBigIntStrippingUnit('0')).toEqual(0n);
expect(StringUtils.parseBigIntStrippingUnit('0 unit')).toEqual(0n);
expect(StringUtils.parseBigIntStrippingUnit('0unit')).toEqual(0n);
expect(StringUtils.parseBigIntStrippingUnit(' 0 unit ')).toEqual(0n);
expect(StringUtils.parseBigIntStrippingUnit('10')).toEqual(10n);
expect(StringUtils.parseBigIntStrippingUnit('10 unit')).toEqual(10n);
expect(StringUtils.parseBigIntStrippingUnit('10unit')).toEqual(10n);
expect(StringUtils.parseBigIntStrippingUnit(' 10 unit ')).toEqual(10n);
expect(() => StringUtils.parseBigIntStrippingUnit('invalid')).toThrow();
expect(() => StringUtils.parseBigIntStrippingUnit('invalid 10 unit')).toThrow();
});
});

View File

@@ -43,7 +43,7 @@ export class TimeUtils {
const units = TimeUtils.units;
let leftNanos = timestampNanos;
const parts = units
const parts: Array<{value: bigint; unit: string}> = units
.slice()
.reverse()
.map(({nanosInUnit, unit}) => {
@@ -52,7 +52,7 @@ export class TimeUtils {
amountOfUnit = leftNanos / BigInt(nanosInUnit);
}
leftNanos = leftNanos % BigInt(nanosInUnit);
return `${amountOfUnit}${unit}`;
return {value: amountOfUnit, unit};
});
if (hideNs) {
@@ -60,11 +60,11 @@ export class TimeUtils {
}
// Remove all 0ed units at start
while (parts.length > 1 && parseInt(parts[0]) === 0) {
while (parts.length > 1 && parts[0].value === 0n) {
parts.shift();
}
return parts.join('');
return parts.map((part) => `${part.value}${part.unit}`).join('');
}
private static nanosecondsToHumanReal(timestampNanos: number | bigint, hideNs = true): string {
@@ -91,14 +91,14 @@ export class TimeUtils {
const usedValues = timestampHuman
.split(/[a-z]+/)
.filter((it) => it !== '')
.map((it) => parseInt(it));
.map((it) => Math.floor(Number(it)));
let ns = BigInt(0);
for (let i = 0; i < usedUnits.length; i++) {
const unit = usedUnits[i];
const value = usedValues[i];
const unitData = units.find((it) => it.unit == unit)!;
const unitData = units.find((it) => it.unit === unit)!;
ns += BigInt(unitData.nanosInUnit) * BigInt(value);
}
@@ -111,7 +111,7 @@ export class TimeUtils {
}
// Add trailing Z if it isn't there yet
if (timestampHuman[timestampHuman.length - 1] != 'Z') {
if (timestampHuman[timestampHuman.length - 1] !== 'Z') {
timestampHuman += 'Z';
}
@@ -119,7 +119,7 @@ export class TimeUtils {
let nanoSeconds = 0;
if (timestampHuman.includes('.')) {
const milliseconds = timestampHuman.split('.')[1].replace('Z', '');
nanoSeconds = parseInt(milliseconds.padEnd(9, '0').slice(3));
nanoSeconds = Math.floor(Number(milliseconds.padEnd(9, '0').slice(3)));
}
return new RealTimestamp(

View File

@@ -23,7 +23,7 @@ interface TreeNode {
type FilterType = (node: TreeNode | undefined | null) => boolean;
class TreeUtils {
public static findDescendantNode(node: TreeNode, isTargetNode: FilterType): TreeNode | undefined {
static findDescendantNode(node: TreeNode, isTargetNode: FilterType): TreeNode | undefined {
if (isTargetNode(node)) {
return node;
}
@@ -33,7 +33,7 @@ class TreeUtils {
}
for (const child of node.children) {
const target = this.findDescendantNode(child, isTargetNode);
const target = TreeUtils.findDescendantNode(child, isTargetNode);
if (target) {
return target;
}
@@ -42,7 +42,7 @@ class TreeUtils {
return undefined;
}
public static findAncestorNode(node: TreeNode, isTargetNode: FilterType): TreeNode | undefined {
static findAncestorNode(node: TreeNode, isTargetNode: FilterType): TreeNode | undefined {
let ancestor = node.parent;
while (ancestor && !isTargetNode(ancestor)) {
@@ -52,7 +52,7 @@ class TreeUtils {
return ancestor;
}
public static makeNodeFilter(filterString: string): FilterType {
static makeNodeFilter(filterString: string): FilterType {
const filterStrings = filterString.split(',');
const positive: any[] = [];
const negative: any[] = [];

View File

@@ -23,7 +23,7 @@ import {Message, MessageBugReport, MessagePong, MessageTimestamp, MessageType} f
import {OriginAllowList} from './origin_allow_list';
class RemoteTool {
constructor(public readonly window: Window, public readonly origin: string) {}
constructor(readonly window: Window, readonly origin: string) {}
}
export class CrossToolProtocol

View File

@@ -17,7 +17,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>WinscopeNg</title>
<title>Winscope</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.svg">

View File

@@ -28,7 +28,7 @@ abstract class Parser {
this.trace = trace;
}
public async parse() {
async parse() {
const traceBuffer = new Uint8Array(await this.trace.file.arrayBuffer());
const magicNumber = this.getMagicNumber();
@@ -97,28 +97,28 @@ abstract class Parser {
return protoObj;
}
public abstract getTraceType(): TraceType;
abstract getTraceType(): TraceType;
public getTrace(): Trace {
getTrace(): Trace {
return {
type: this.getTraceType(),
traceFile: this.trace,
};
}
public getTimestamps(type: TimestampType): undefined | Timestamp[] {
getTimestamps(type: TimestampType): undefined | Timestamp[] {
return this.timestamps.get(type);
}
//TODO (b/256564627): include this into the new type/abstraction passed to viewers
public getEntriesLength(): number {
getEntriesLength(): number {
return this.decodedEntries.length;
}
//TODO (b/256564627):
// - factor out timestamp search policy. Receive index parameter instead.
// - make async for possible lazy disk reads in the future
public getTraceEntry(timestamp: Timestamp): undefined | any {
getTraceEntry(timestamp: Timestamp): undefined | any {
const timestamps = this.getTimestamps(timestamp.getType());
if (timestamps === undefined) {
throw TypeError(`Timestamps with type "${timestamp.getType()}" not available`);

View File

@@ -35,7 +35,7 @@ class ParserAccessibility extends Parser {
}
override decodeTrace(buffer: Uint8Array): any[] {
const decoded = <any>AccessibilityTraceFileProto.decode(buffer);
const decoded = AccessibilityTraceFileProto.decode(buffer) as any;
if (Object.prototype.hasOwnProperty.call(decoded, 'realToElapsedTimeOffsetNanos')) {
this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos);
} else {

View File

@@ -38,20 +38,20 @@ class ParserInputMethodClients extends Parser {
}
override decodeTrace(buffer: Uint8Array): any[] {
const decoded = <any>InputMethodClientsTraceFileProto.decode(buffer);
const decoded = InputMethodClientsTraceFileProto.decode(buffer) as any;
if (Object.prototype.hasOwnProperty.call(decoded, 'realToElapsedTimeOffsetNanos')) {
this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos);
} else {
this.realToElapsedTimeOffsetNs = undefined;
}
return (<any>InputMethodClientsTraceFileProto.decode(buffer)).entry;
return (InputMethodClientsTraceFileProto.decode(buffer) as any).entry;
}
override getTimestamp(type: TimestampType, entryProto: any): undefined | Timestamp {
if (type === TimestampType.ELAPSED) {
return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos));
} else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs != undefined) {
} else if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) {
return new Timestamp(
type,
BigInt(entryProto.elapsedRealtimeNanos) + this.realToElapsedTimeOffsetNs

View File

@@ -37,7 +37,7 @@ class ParserInputMethodManagerService extends Parser {
}
override decodeTrace(buffer: Uint8Array): any[] {
const decoded = <any>InputMethodManagerServiceTraceFileProto.decode(buffer);
const decoded = InputMethodManagerServiceTraceFileProto.decode(buffer) as any;
if (Object.prototype.hasOwnProperty.call(decoded, 'realToElapsedTimeOffsetNanos')) {
this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos);
} else {

View File

@@ -38,7 +38,7 @@ class ParserInputMethodService extends Parser {
}
override decodeTrace(buffer: Uint8Array): any[] {
const decoded = <any>InputMethodServiceTraceFileProto.decode(buffer);
const decoded = InputMethodServiceTraceFileProto.decode(buffer) as any;
if (Object.prototype.hasOwnProperty.call(decoded, 'realToElapsedTimeOffsetNanos')) {
this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos);
} else {

View File

@@ -65,10 +65,10 @@ class ParserProtoLog extends Parser {
}
override getTimestamp(type: TimestampType, entryProto: any): undefined | Timestamp {
if (type == TimestampType.ELAPSED) {
if (type === TimestampType.ELAPSED) {
return new Timestamp(type, BigInt(entryProto.elapsedRealtimeNanos));
}
if (type == TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) {
if (type === TimestampType.REAL && this.realToElapsedTimeOffsetNs !== undefined) {
return new Timestamp(
type,
BigInt(entryProto.elapsedRealtimeNanos) + this.realToElapsedTimeOffsetNs
@@ -93,7 +93,7 @@ class ParserProtoLog extends Parser {
}
private decodeProtoLogMessage(entryProto: any, timestampType: TimestampType): LogMessage {
const message = (<any>configJson).messages[entryProto.messageHash];
const message = (configJson as any).messages[entryProto.messageHash];
if (!message) {
return new FormattedLogMessage(entryProto, timestampType, this.realToElapsedTimeOffsetNs);
}

View File

@@ -144,11 +144,15 @@ class ParserScreenRecording extends Parser {
return [pos, count];
}
private parseTimestampsElapsedNs(videoData: Uint8Array, pos: number, count: number): bigint[] {
private parseTimestampsElapsedNs(
videoData: Uint8Array,
pos: number,
count: number
): Array<bigint> {
if (pos + count * 8 > videoData.length) {
throw new TypeError('Failed to parse timestamps. Video data is too short.');
}
const timestamps: bigint[] = [];
const timestamps: Array<bigint> = [];
for (let i = 0; i < count; ++i) {
const timestamp = ArrayUtils.toUintLittleEndian(videoData, pos, pos + 8);
pos += 8;

View File

@@ -36,7 +36,7 @@ class ParserSurfaceFlinger extends Parser {
}
override decodeTrace(buffer: Uint8Array): any[] {
const decoded = <any>LayersTraceFileProto.decode(buffer);
const decoded = LayersTraceFileProto.decode(buffer) as any;
if (Object.prototype.hasOwnProperty.call(decoded, 'realToElapsedTimeOffsetNanos')) {
this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos);
} else {

View File

@@ -36,7 +36,7 @@ class ParserTransactions extends Parser {
}
override decodeTrace(buffer: Uint8Array): any[] {
const decodedProto = <any>TransactionsTraceFileProto.decode(buffer);
const decodedProto = TransactionsTraceFileProto.decode(buffer) as any;
this.decodeWhatFields(decodedProto);
if (Object.prototype.hasOwnProperty.call(decodedProto, 'realToElapsedTimeOffsetNanos')) {
@@ -51,22 +51,23 @@ class ParserTransactions extends Parser {
const decodeBitset32 = (bitset: number, EnumProto: any) => {
return Object.keys(EnumProto).filter((key) => {
const value = EnumProto[key];
return (bitset & value) != 0;
return (bitset & value) !== 0;
});
};
const concatBitsetTokens = (tokens: string[]) => {
if (tokens.length == 0) {
if (tokens.length === 0) {
return '0';
}
return tokens.join(' | ');
};
const LayerStateChangesLsbEnum = (<any>TransactionsTraceFileProto?.parent).LayerState
const LayerStateChangesLsbEnum = (TransactionsTraceFileProto?.parent as any).LayerState
.ChangesLsb;
const LayerStateChangesMsbEnum = (<any>TransactionsTraceFileProto?.parent).LayerState
const LayerStateChangesMsbEnum = (TransactionsTraceFileProto?.parent as any).LayerState
.ChangesMsb;
const DisplayStateChangesEnum = (<any>TransactionsTraceFileProto?.parent).DisplayState.Changes;
const DisplayStateChangesEnum = (TransactionsTraceFileProto?.parent as any).DisplayState
.Changes;
decodedProto.entry.forEach((transactionTraceEntry: any) => {
transactionTraceEntry.transactions.forEach((transactionState: any) => {

View File

@@ -35,7 +35,7 @@ class ParserWindowManager extends Parser {
}
override decodeTrace(buffer: Uint8Array): any[] {
const decoded = <any>WindowManagerTraceFileProto.decode(buffer);
const decoded = WindowManagerTraceFileProto.decode(buffer) as any;
if (Object.prototype.hasOwnProperty.call(decoded, 'realToElapsedTimeOffsetNanos')) {
this.realToElapsedTimeOffsetNs = BigInt(decoded.realToElapsedTimeOffsetNanos);
} else {

View File

@@ -73,17 +73,17 @@ export class AppComponent {
});
}
public async onButtonOpenWinscopeClick() {
async onButtonOpenWinscopeClick() {
this.openWinscope();
await this.waitWinscopeUp();
}
public async onUploadBugreport(event: Event) {
async onUploadBugreport(event: Event) {
const [file, buffer] = await this.readInputFile(event);
this.sendBugreport(file, buffer);
}
public onButtonSendTimestampClick() {
onButtonSendTimestampClick() {
const inputTimestampElement = document.querySelector('.input-timestamp')! as HTMLInputElement;
this.sendTimestamp(BigInt(inputTimestampElement.value));
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Chip from 'viewers/common/chip';
import {Chip} from 'viewers/common/chip';
import {HierarchyTreeNode} from 'viewers/common/ui_tree_utils';
class HierarchyTreeBuilder {

View File

@@ -31,11 +31,11 @@ class UnitTestUtils extends CommonTestUtils {
}
static async getWindowManagerState(): Promise<WindowManagerState> {
return this.getTraceEntry('traces/elapsed_timestamp/WindowManager.pb');
return UnitTestUtils.getTraceEntry('traces/elapsed_timestamp/WindowManager.pb');
}
static async getLayerTraceEntry(): Promise<LayerTraceEntry> {
return await this.getTraceEntry('traces/elapsed_timestamp/SurfaceFlinger.pb');
return await UnitTestUtils.getTraceEntry('traces/elapsed_timestamp/SurfaceFlinger.pb');
}
static async getImeTraceEntries(): Promise<Map<TraceType, any>> {
@@ -55,15 +55,15 @@ class UnitTestUtils extends CommonTestUtils {
const entries = new Map<TraceType, any>();
entries.set(TraceType.INPUT_METHOD_CLIENTS, [
await this.getTraceEntry('traces/ime/InputMethodClients.pb'),
await UnitTestUtils.getTraceEntry('traces/ime/InputMethodClients.pb'),
null,
]);
entries.set(TraceType.INPUT_METHOD_MANAGER_SERVICE, [
await this.getTraceEntry('traces/ime/InputMethodManagerService.pb'),
await UnitTestUtils.getTraceEntry('traces/ime/InputMethodManagerService.pb'),
null,
]);
entries.set(TraceType.INPUT_METHOD_SERVICE, [
await this.getTraceEntry('traces/ime/InputMethodService.pb'),
await UnitTestUtils.getTraceEntry('traces/ime/InputMethodService.pb'),
null,
]);
entries.set(TraceType.SURFACE_FLINGER, [surfaceFlingerEntry, null]);
@@ -73,7 +73,7 @@ class UnitTestUtils extends CommonTestUtils {
}
private static async getTraceEntry(filename: string) {
const parser = await this.getParser(filename);
const parser = await UnitTestUtils.getParser(filename);
const timestamp = parser.getTimestamps(TimestampType.ELAPSED)![0];
return parser.getTraceEntry(timestamp);
}

View File

@@ -38,13 +38,14 @@ function readIntdefMap(): Map<string, string> {
const keys = Object.keys(config.intDefColumn);
keys.forEach((key) => {
const value = config.intDefColumn[<keyof typeof config.intDefColumn>key];
const value = config.intDefColumn[key as keyof typeof config.intDefColumn];
map.set(key, value);
});
return map;
}
export default class ObjectFormatter {
export class ObjectFormatter {
static displayDefaults: boolean = false;
private static INVALID_ELEMENT_PROPERTIES = config.invalidProperties;
@@ -77,7 +78,7 @@ export default class ObjectFormatter {
// private kotlin variables from kotlin
if (it.startsWith(`_`)) return false;
// some predefined properties used only internally (e.g., children, ref, diff)
if (this.INVALID_ELEMENT_PROPERTIES.includes(it)) return false;
if (ObjectFormatter.INVALID_ELEMENT_PROPERTIES.includes(it)) return false;
const value = entry[it];
// only non-empty arrays of non-flicker objects (otherwise they are in hierarchy)
@@ -85,7 +86,7 @@ export default class ObjectFormatter {
// non-flicker object
return !value?.stableId;
});
properties.forEach(function (prop) {
properties.forEach((prop) => {
if (typeof entry[prop] !== 'function' && props.indexOf(prop) === -1) {
props.push(prop);
}
@@ -103,7 +104,7 @@ export default class ObjectFormatter {
* @return The formatted object
*/
static format(obj: any): PropertiesDump {
const properties = this.getProperties(obj);
const properties = ObjectFormatter.getProperties(obj);
const sortedProperties = properties.sort();
const result: PropertiesDump = {};
@@ -112,25 +113,25 @@ export default class ObjectFormatter {
const value: any = obj[key];
if (value === null || value === undefined) {
if (this.displayDefaults) {
if (ObjectFormatter.displayDefaults) {
result[key] = value;
}
return;
}
if (value || this.displayDefaults) {
if (value || ObjectFormatter.displayDefaults) {
// raw values (e.g., false or 0)
if (!value) {
result[key] = value;
// flicker obj
} else if (value.prettyPrint) {
const isEmpty = value.isEmpty === true;
if (!isEmpty || this.displayDefaults) {
if (!isEmpty || ObjectFormatter.displayDefaults) {
result[key] = value.prettyPrint();
}
} else {
// converted proto to flicker
const translatedObject = this.translateObject(key, value);
const translatedObject = ObjectFormatter.translateObject(key, value);
if (translatedObject) {
if (translatedObject.prettyPrint) {
result[key] = translatedObject.prettyPrint();
@@ -138,15 +139,15 @@ export default class ObjectFormatter {
result[key] = translatedObject;
}
// objects - recursive call
} else if (value && typeof value == `object`) {
const childObj = this.format(value) as any;
const isEmpty = Object.entries(childObj).length == 0 || childObj.isEmpty;
if (!isEmpty || this.displayDefaults) {
} else if (value && typeof value === `object`) {
const childObj = ObjectFormatter.format(value) as any;
const isEmpty = Object.entries(childObj).length === 0 || childObj.isEmpty;
if (!isEmpty || ObjectFormatter.displayDefaults) {
result[key] = childObj;
}
} else {
// values
result[key] = this.translateIntDef(obj, key, value);
result[key] = ObjectFormatter.translateIntDef(obj, key, value);
}
}
}
@@ -192,9 +193,11 @@ export default class ObjectFormatter {
case `TransformProto`:
return toTransform(obj);
case 'ColorTransformProto': {
const formatted = this.formatColorTransform(obj.val);
const formatted = ObjectFormatter.formatColorTransform(obj.val);
return `${formatted}`;
}
default:
// handle other cases below
}
// Raw long number (no type name, no constructor name, no useful toString() method)
@@ -256,16 +259,16 @@ export default class ObjectFormatter {
let translatedValue: string = value;
// Parse Flicker objects (no intdef annotation supported)
if (this.FLICKER_INTDEF_MAP.has(propertyPath)) {
translatedValue = this.getIntFlagsAsStrings(
if (ObjectFormatter.FLICKER_INTDEF_MAP.has(propertyPath)) {
translatedValue = ObjectFormatter.getIntFlagsAsStrings(
value,
<string>this.FLICKER_INTDEF_MAP.get(propertyPath)
ObjectFormatter.FLICKER_INTDEF_MAP.get(propertyPath) as string
);
} else {
// If it's a proto, search on the proto definition for the intdef type
const typeDefSpec = this.getTypeDefSpec(parentObj, propertyName);
const typeDefSpec = ObjectFormatter.getTypeDefSpec(parentObj, propertyName);
if (typeDefSpec) {
translatedValue = this.getIntFlagsAsStrings(value, typeDefSpec);
translatedValue = ObjectFormatter.getIntFlagsAsStrings(value, typeDefSpec);
}
}
@@ -281,18 +284,18 @@ export default class ObjectFormatter {
private static getIntFlagsAsStrings(intFlags: any, annotationType: string): string {
const flags = [];
const mapping = intDefMapping[<keyof typeof intDefMapping>annotationType].values;
const mapping = intDefMapping[annotationType as keyof typeof intDefMapping].values;
const knownFlagValues = Object.keys(mapping)
.reverse()
.map((x) => parseInt(x));
.map((x) => Math.floor(Number(x)));
if (knownFlagValues.length == 0) {
if (knownFlagValues.length === 0) {
console.warn('No mapping for type', annotationType);
return intFlags + '';
}
// Will only contain bits that have not been associated with a flag.
const parsedIntFlags = parseInt(intFlags);
const parsedIntFlags = Math.floor(Number(intFlags));
let leftOver = parsedIntFlags;
for (const flagValue of knownFlagValues) {
@@ -300,7 +303,7 @@ export default class ObjectFormatter {
(leftOver & flagValue && (intFlags & flagValue) === flagValue) ||
(parsedIntFlags === 0 && flagValue === 0)
) {
flags.push(mapping[<keyof typeof mapping>flagValue]);
flags.push(mapping[flagValue as keyof typeof mapping]);
leftOver = leftOver & ~flagValue;
}

View File

@@ -25,9 +25,9 @@ import {
toRegion,
} from '../common';
import {shortenName} from '../mixin';
import Transform from './Transform';
import {Transform} from './Transform';
Layer.fromProto = function (proto: any, excludesCompositionState = false): Layer {
Layer.fromProto = (proto: any, excludesCompositionState = false): Layer => {
const visibleRegion = toRegion(proto.visibleRegion);
const activeBuffer = toActiveBuffer(proto.activeBuffer);
const bounds = toRectF(proto.bounds);

View File

@@ -27,7 +27,7 @@ import {
import {getPropertiesForDisplay} from '../mixin';
import {Layer} from './Layer';
LayerTraceEntry.fromProto = function (
LayerTraceEntry.fromProto = (
protos: object[],
displayProtos: object[],
elapsedTimestamp: bigint,
@@ -37,7 +37,7 @@ LayerTraceEntry.fromProto = function (
realToElapsedTimeOffsetNs: bigint | undefined = undefined,
useElapsedTime = false,
excludesCompositionState = false
): LayerTraceEntry {
): LayerTraceEntry => {
const layers = protos.map((it) => Layer.fromProto(it, excludesCompositionState));
const displays = (displayProtos || []).map((it) => newDisplay(it));
const builder = new LayerTraceEntryBuilder(
@@ -67,7 +67,7 @@ function addAttributes(entry: LayerTraceEntry, protos: object[], useElapsedTime
if (newObj.physicalDisplayBounds) delete newObj.physicalDisplayBounds;
if (newObj.isVisible) delete newObj.isVisible;
entry.proto = newObj;
if (useElapsedTime || entry.clockTimestamp == undefined) {
if (useElapsedTime || entry.clockTimestamp === undefined) {
entry.name = TimeUtils.format(new ElapsedTimestamp(BigInt(entry.elapsedTimestamp)));
entry.shortName = entry.name;
} else {

View File

@@ -16,7 +16,7 @@
import {Matrix33, Transform} from '../common';
Transform.fromProto = function (transformProto: any, positionProto: any): Transform {
Transform.fromProto = (transformProto: any, positionProto: any): Transform => {
const entry = new Transform(transformProto?.type ?? 0, getMatrix(transformProto, positionProto));
return entry;
@@ -62,16 +62,16 @@ function getDefaultTransform(type: number, x: number, y: number): Matrix33 {
throw new Error(`Unknown transform type ${type}`);
}
export function isFlagSet(type: number, bits: number): Boolean {
export function isFlagSet(type: number, bits: number): boolean {
type = type || 0;
return (type & bits) === bits;
}
export function isFlagClear(type: number, bits: number): Boolean {
export function isFlagClear(type: number, bits: number): boolean {
return (type & bits) === 0;
}
export function isSimpleTransform(type: number): Boolean {
export function isSimpleTransform(type: number): boolean {
return isFlagClear(type, ROT_INVALID_VAL | SCALE_VAL);
}
@@ -85,4 +85,4 @@ const FLIP_V_VAL = 0x0200; // (1 << 1 << 8)
const ROT_90_VAL = 0x0400; // (1 << 2 << 8)
const ROT_INVALID_VAL = 0x8000; // (0x80 << 8)
export default Transform;
export {Transform};

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
import ObjectFormatter from './ObjectFormatter';
import {ObjectFormatter} from './ObjectFormatter';
/**
* Get the properties of a WM object for display.

View File

@@ -16,9 +16,9 @@
import {Activity} from '../common';
import {shortenName} from '../mixin';
import WindowContainer from './WindowContainer';
import {WindowContainer} from './WindowContainer';
Activity.fromProto = function (proto: any, nextSeq: () => number): Activity {
Activity.fromProto = (proto: any, nextSeq: () => number): Activity => {
if (proto == null) {
return null;
} else {
@@ -52,4 +52,4 @@ function addAttributes(entry: Activity, proto: any) {
entry.shortName = shortenName(entry.name);
}
export default Activity;
export {Activity};

View File

@@ -16,13 +16,13 @@
import {DisplayArea} from '../common';
import {shortenName} from '../mixin';
import WindowContainer from './WindowContainer';
import {WindowContainer} from './WindowContainer';
DisplayArea.fromProto = function (
DisplayArea.fromProto = (
proto: any,
isActivityInTree: Boolean,
isActivityInTree: boolean,
nextSeq: () => number
): DisplayArea {
): DisplayArea => {
if (proto == null) {
return null;
} else {
@@ -47,4 +47,4 @@ function addAttributes(entry: DisplayArea, proto: any) {
entry.shortName = shortenName(entry.name);
}
export default DisplayArea;
export {DisplayArea};

View File

@@ -16,13 +16,13 @@
import {DisplayContent, DisplayCutout, PlatformConsts, Rect, toInsets, toRect} from '../common';
import {shortenName} from '../mixin';
import WindowContainer from './WindowContainer';
import {WindowContainer} from './WindowContainer';
DisplayContent.fromProto = function (
DisplayContent.fromProto = (
proto: any,
isActivityInTree: Boolean,
isActivityInTree: boolean,
nextSeq: () => number
): DisplayContent {
): DisplayContent => {
if (proto == null) {
return null;
} else {
@@ -88,4 +88,4 @@ function addAttributes(entry: DisplayContent, proto: any) {
entry.shortName = shortenName(entry.name);
}
export default DisplayContent;
export {DisplayContent};

View File

@@ -16,9 +16,9 @@
import {Task, toRect} from '../common';
import {shortenName} from '../mixin';
import WindowContainer from './WindowContainer';
import {WindowContainer} from './WindowContainer';
Task.fromProto = function (proto: any, isActivityInTree: Boolean, nextSeq: () => number): Task {
Task.fromProto = (proto: any, isActivityInTree: boolean, nextSeq: () => number): Task => {
if (proto == null) {
return null;
} else {
@@ -62,4 +62,4 @@ function addAttributes(entry: Task, proto: any) {
entry.shortName = shortenName(entry.name);
}
export default Task;
export {Task};

View File

@@ -16,13 +16,13 @@
import {TaskFragment} from '../common';
import {shortenName} from '../mixin';
import WindowContainer from './WindowContainer';
import {WindowContainer} from './WindowContainer';
TaskFragment.fromProto = function (
TaskFragment.fromProto = (
proto: any,
isActivityInTree: Boolean,
isActivityInTree: boolean,
nextSeq: () => number
): TaskFragment {
): TaskFragment => {
if (proto == null) {
return null;
} else {
@@ -51,4 +51,4 @@ function addAttributes(entry: TaskFragment, proto: any) {
entry.shortName = shortenName(entry.name);
}
export default TaskFragment;
export {TaskFragment};

View File

@@ -24,15 +24,15 @@ import {
WindowContainer,
} from '../common';
import Activity from './Activity';
import DisplayArea from './DisplayArea';
import DisplayContent from './DisplayContent';
import Task from './Task';
import TaskFragment from './TaskFragment';
import WindowState from './WindowState';
import WindowToken from './WindowToken';
import {Activity} from './Activity';
import {DisplayArea} from './DisplayArea';
import {DisplayContent} from './DisplayContent';
import {Task} from './Task';
import {TaskFragment} from './TaskFragment';
import {WindowState} from './WindowState';
import {WindowToken} from './WindowToken';
WindowContainer.fromProto = function (
WindowContainer.fromProto = (
proto: any,
protoChildren: any[],
isActivityInTree: boolean,
@@ -40,7 +40,7 @@ WindowContainer.fromProto = function (
nameOverride: string | null = null,
identifierOverride: string | null = null,
tokenOverride: any = null
): WindowContainer {
): WindowContainer => {
if (proto == null) {
return null;
}
@@ -87,11 +87,11 @@ type WindowContainerChildType =
| WindowState
| WindowContainer;
WindowContainer.childrenFromProto = function (
WindowContainer.childrenFromProto = (
proto: any,
isActivityInTree: Boolean,
isActivityInTree: boolean,
nextSeq: () => number
): WindowContainerChildType {
): WindowContainerChildType => {
return (
DisplayContent.fromProto(proto.displayContent, isActivityInTree, nextSeq) ??
DisplayArea.fromProto(proto.displayArea, isActivityInTree, nextSeq) ??
@@ -147,4 +147,4 @@ function createWindowConfiguration(proto: any): WindowConfiguration {
);
}
export default WindowContainer;
export {WindowContainer};

View File

@@ -25,15 +25,15 @@ import {
WindowManagerTraceEntryBuilder,
} from '../common';
import WindowContainer from './WindowContainer';
import {WindowContainer} from './WindowContainer';
WindowManagerState.fromProto = function (
WindowManagerState.fromProto = (
proto: any,
elapsedTimestamp: bigint = 0n,
where: string = '',
realToElapsedTimeOffsetNs: bigint | undefined = undefined,
useElapsedTime = false
): WindowManagerState {
): WindowManagerState => {
const inputMethodWIndowAppToken = '';
if (proto.inputMethodWindow != null) {
proto.inputMethodWindow.hashCode.toString(16);
@@ -73,7 +73,7 @@ function addAttributes(entry: WindowManagerState, proto: any, useElapsedTime = f
entry.isIncompleteReason = entry.getIsIncompleteReason();
}
entry.proto = proto;
if (useElapsedTime || entry.clockTimestamp == undefined) {
if (useElapsedTime || entry.clockTimestamp === undefined) {
entry.name = TimeUtils.format(new ElapsedTimestamp(BigInt(entry.elapsedTimestamp)));
entry.shortName = entry.name;
} else {
@@ -122,7 +122,7 @@ function createKeyguardControllerState(proto: any): KeyguardControllerState {
if (proto) {
proto.keyguardOccludedStates.forEach(
(it: any) =>
(keyguardOccludedStates[<keyof typeof keyguardOccludedStates>it.displayId] =
(keyguardOccludedStates[it.displayId as keyof typeof keyguardOccludedStates] =
it.keyguardOccluded)
);
}

View File

@@ -16,13 +16,13 @@
import {Size, toRect, WindowLayoutParams, WindowState} from '../common';
import {shortenName} from '../mixin';
import WindowContainer from './WindowContainer';
import {WindowContainer} from './WindowContainer';
WindowState.fromProto = function (
WindowState.fromProto = (
proto: any,
isActivityInTree: Boolean,
isActivityInTree: boolean,
nextSeq: () => number
): WindowState {
): WindowState => {
if (proto == null) {
return null;
} else {
@@ -137,4 +137,4 @@ function addAttributes(entry: WindowState, proto: any) {
entry.shortName = shortenName(entry.name);
}
export default WindowState;
export {WindowState};

View File

@@ -16,14 +16,14 @@
import {WindowToken} from '../common';
import {shortenName} from '../mixin';
import WindowContainer from './WindowContainer';
import {WindowContainer} from './WindowContainer';
WindowToken.fromProto = function (
WindowToken.fromProto = (
proto: any,
isActivityInTree: Boolean,
isActivityInTree: boolean,
nextSeq: () => number
): WindowToken {
if (proto == null) {
): WindowToken => {
if (!proto) {
return null;
}
@@ -43,4 +43,4 @@ WindowToken.fromProto = function (
return entry;
};
export default WindowToken;
export {WindowToken};

View File

@@ -69,7 +69,7 @@ class FormattedLogMessage extends LogMessage {
if (
timestampType === TimestampType.REAL &&
realToElapsedTimeOffsetNs !== undefined &&
realToElapsedTimeOffsetNs != 0n
realToElapsedTimeOffsetNs !== 0n
) {
timestamp = realToElapsedTimeOffsetNs + BigInt(proto.elapsedRealtimeNanos);
time = TimeUtils.format(new RealTimestamp(timestamp));
@@ -94,7 +94,7 @@ class UnformattedLogMessage extends LogMessage {
if (
timestampType === TimestampType.REAL &&
realToElapsedTimeOffsetNs !== undefined &&
realToElapsedTimeOffsetNs != 0n
realToElapsedTimeOffsetNs !== 0n
) {
timestamp = realToElapsedTimeOffsetNs + BigInt(proto.elapsedRealtimeNanos);
time = TimeUtils.format(
@@ -108,7 +108,7 @@ class UnformattedLogMessage extends LogMessage {
super(
formatText(message.message, proto),
time,
(<any>configJson).groups[message.group].tag,
(configJson as any).groups[message.group].tag,
message.level,
message.at,
timestamp
@@ -129,7 +129,7 @@ function formatText(messageFormat: any, data: any) {
let booleanParamsIdx = 0;
for (let i = 0; i < messageFormat.length; ) {
if (messageFormat[i] == '%') {
if (messageFormat[i] === '%') {
if (i + 1 >= messageFormat.length) {
// Should never happen - protologtool checks for that
throw new Error('Invalid format string');

View File

@@ -43,15 +43,15 @@ export class Timestamp {
}
}
public getType(): TimestampType {
getType(): TimestampType {
return this.type;
}
public getValueNs(): bigint {
getValueNs(): bigint {
return this.valueNs;
}
public valueOf(): bigint {
valueOf(): bigint {
return this.getValueNs();
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
import {ProxyClient} from 'trace_collection/proxy_client';
import {configMap} from './trace_collection_utils';
import {ConfigMap} from './trace_collection_utils';
export interface Device {
[key: string]: DeviceProperties;
@@ -44,12 +44,12 @@ export interface Connection {
isConnectingState(): boolean;
throwNoTargetsError(): any;
startTrace(
reqEnableConfig?: Array<string>,
reqSelectedSfConfig?: configMap,
reqSelectedWmConfig?: configMap
reqEnableConfig?: string[],
reqSelectedSfConfig?: ConfigMap,
reqSelectedWmConfig?: ConfigMap
): any;
endTrace(): any;
adbData(): Array<File>;
adbData(): File[];
dumpState(): any;
proxy?: ProxyClient;
}

View File

@@ -17,7 +17,7 @@
import {OnProgressUpdateType} from 'common/function_utils';
import {PersistentStore} from 'common/persistent_store';
import {Device} from './connection';
import {configMap} from './trace_collection_utils';
import {ConfigMap} from './trace_collection_utils';
export enum ProxyState {
ERROR = 0,
@@ -118,7 +118,7 @@ class ProxyRequest {
await proxyRequest.call('GET', ProxyEndpoint.DEVICES, proxyRequest.onSuccessGetDevices);
}
async setEnabledConfig(view: any, req: Array<string>) {
async setEnabledConfig(view: any, req: string[]) {
await proxyRequest.call(
'POST',
`${ProxyEndpoint.ENABLE_CONFIG_TRACE}${view.proxy.selectedDevice}/`,
@@ -128,7 +128,7 @@ class ProxyRequest {
);
}
async setSelectedConfig(endpoint: ProxyEndpoint, view: any, req: configMap) {
async setSelectedConfig(endpoint: ProxyEndpoint, view: any, req: ConfigMap) {
await proxyRequest.call(
'POST',
`${endpoint}${view.proxy.selectedDevice}/`,
@@ -192,7 +192,7 @@ class ProxyRequest {
);
}
onSuccessGetDevices = function (request: XMLHttpRequest) {
onSuccessGetDevices = (request: XMLHttpRequest) => {
const client = proxyClient;
try {
client.devices = JSON.parse(request.responseText);
@@ -225,7 +225,7 @@ class ProxyRequest {
const resp = enc.decode(request.response);
const filesByType = JSON.parse(resp);
for (const filetype in filesByType) {
for (const filetype of Object.keys(filesByType)) {
const files = filesByType[filetype];
for (const encodedFileBuffer of files) {
const buffer = Uint8Array.from(atob(encodedFileBuffer), (c) => c.charCodeAt(0));
@@ -246,7 +246,7 @@ class ProxyRequest {
export const proxyRequest = new ProxyRequest();
interface AdbParams {
files: Array<string>;
files: string[];
idx: number;
traceType: string;
}
@@ -256,12 +256,12 @@ export class ProxyClient {
readonly WINSCOPE_PROXY_URL = 'http://localhost:5544';
readonly VERSION = '1.0';
state: ProxyState = ProxyState.CONNECTING;
stateChangeListeners: {(param: ProxyState, errorText: string): void}[] = [];
stateChangeListeners: Array<{(param: ProxyState, errorText: string): void}> = [];
refresh_worker: NodeJS.Timer | null = null;
devices: Device = {};
selectedDevice = '';
errorText = '';
adbData: Array<File> = [];
adbData: File[] = [];
proxyKey = '';
lastDevice = '';
store = new PersistentStore();
@@ -298,11 +298,7 @@ export class ProxyClient {
this.setState(ProxyState.START_TRACE);
}
async updateAdbData(
files: Array<string>,
traceType: string,
progressCallback: OnProgressUpdateType
) {
async updateAdbData(files: string[], traceType: string, progressCallback: OnProgressUpdateType) {
for (let idx = 0; idx < files.length; idx++) {
const adbParams = {
files,

View File

@@ -17,7 +17,7 @@
import {FunctionUtils, OnProgressUpdateType} from 'common/function_utils';
import {proxyClient, ProxyEndpoint, proxyRequest, ProxyState} from 'trace_collection/proxy_client';
import {Connection, DeviceProperties} from './connection';
import {configMap} from './trace_collection_utils';
import {ConfigMap} from './trace_collection_utils';
import {TracingConfig} from './tracing_config';
export class ProxyConnection implements Connection {
@@ -40,78 +40,78 @@ export class ProxyConnection implements Connection {
this.proxy.getDevices();
}
public devices() {
devices() {
return this.proxy.devices;
}
public adbData() {
adbData() {
return this.proxy.adbData;
}
public state() {
state() {
return this.proxy.state;
}
public isDevicesState() {
isDevicesState() {
return this.state() === ProxyState.DEVICES;
}
public isStartTraceState() {
isStartTraceState() {
return this.state() === ProxyState.START_TRACE;
}
public isErrorState() {
isErrorState() {
return this.state() === ProxyState.ERROR;
}
public isEndTraceState() {
isEndTraceState() {
return this.state() === ProxyState.END_TRACE;
}
public isLoadDataState() {
isLoadDataState() {
return this.state() === ProxyState.LOAD_DATA;
}
public isConnectingState() {
isConnectingState() {
return this.state() === ProxyState.CONNECTING;
}
public throwNoTargetsError() {
throwNoTargetsError() {
this.proxy.setState(ProxyState.ERROR, 'No targets selected');
}
public setProxyKey(key: string) {
setProxyKey(key: string) {
this.proxy.proxyKey = key;
this.proxy.store.add('adb.proxyKey', key);
this.restart();
}
public adbSuccess() {
adbSuccess() {
return !this.notConnected.includes(this.proxy.state);
}
public selectedDevice(): DeviceProperties {
selectedDevice(): DeviceProperties {
return this.proxy.devices[this.proxy.selectedDevice];
}
public selectedDeviceId(): string {
selectedDeviceId(): string {
return this.proxy.selectedDevice;
}
public restart() {
restart() {
this.proxy.setState(ProxyState.CONNECTING);
}
public resetLastDevice() {
resetLastDevice() {
this.proxy.store.add('adb.lastDevice', '');
this.restart();
}
public selectDevice(id: string) {
selectDevice(id: string) {
this.proxy.selectDevice(id);
}
public keepAliveTrace(view: ProxyConnection) {
keepAliveTrace(view: ProxyConnection) {
if (!view.isEndTraceState()) {
clearInterval(view.keep_alive_worker);
view.keep_alive_worker = null;
@@ -120,10 +120,10 @@ export class ProxyConnection implements Connection {
proxyRequest.keepTraceAlive(view);
}
public startTrace(
reqEnableConfig?: Array<string>,
reqSelectedSfConfig?: configMap,
reqSelectedWmConfig?: configMap
startTrace(
reqEnableConfig?: string[],
reqSelectedSfConfig?: ConfigMap,
reqSelectedWmConfig?: ConfigMap
) {
if (reqEnableConfig) {
proxyRequest.setEnabledConfig(this, reqEnableConfig);
@@ -146,13 +146,13 @@ export class ProxyConnection implements Connection {
proxyRequest.startTrace(this, TracingConfig.getInstance().requestedTraces);
}
public async endTrace() {
async endTrace() {
this.progressCallback(0);
this.proxy.setState(ProxyState.LOAD_DATA);
await proxyRequest.endTrace(this, this.progressCallback);
}
public async dumpState(): Promise<boolean> {
async dumpState(): Promise<boolean> {
this.progressCallback(0);
if (TracingConfig.getInstance().requestedDumps.length < 1) {
console.error('No targets selected');
@@ -168,15 +168,15 @@ export class ProxyConnection implements Connection {
return true;
}
public async isWaylandAvailable(): Promise<boolean> {
async isWaylandAvailable(): Promise<boolean> {
return new Promise((resolve, reject) => {
proxyRequest.call('GET', ProxyEndpoint.CHECK_WAYLAND, (request: XMLHttpRequest) => {
resolve(request.responseText == 'true');
resolve(request.responseText === 'true');
});
});
}
public async onConnectChange(newState: ProxyState) {
async onConnectChange(newState: ProxyState) {
if (newState === ProxyState.CONNECTING) {
proxyClient.getDevices();
}

View File

@@ -1,41 +1,53 @@
import {StoreObject} from 'common/persistent_store_proxy';
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export type TraceConfiguration = {
[key: string]: string | boolean | undefined | StoreObject;
export interface TraceConfiguration {
name: string | undefined;
run: boolean | undefined;
isTraceCollection: boolean | undefined;
config: ConfigurationOptions | undefined;
};
}
export type TraceConfigurationMap = {
export interface TraceConfigurationMap {
[key: string]: TraceConfiguration;
};
}
type ConfigurationOptions = {
[key: string]: string | boolean | undefined | StoreObject;
interface ConfigurationOptions {
enableConfigs: EnableConfiguration[];
selectionConfigs: SelectionConfiguration[];
};
}
export type EnableConfiguration = {
export interface EnableConfiguration {
name: string;
key: string;
enabled: boolean;
};
}
export type SelectionConfiguration = {
export interface SelectionConfiguration {
key: string;
name: string;
options: string[];
value: string;
};
}
export type configMap = {
export interface ConfigMap {
[key: string]: string[] | string;
};
}
const wmTraceSelectionConfigs: Array<SelectionConfiguration> = [
const wmTraceSelectionConfigs: SelectionConfiguration[] = [
{
key: 'wmbuffersize',
name: 'buffer size (KB)',
@@ -56,7 +68,7 @@ const wmTraceSelectionConfigs: Array<SelectionConfiguration> = [
},
];
const sfTraceEnableConfigs: Array<EnableConfiguration> = [
const sfTraceEnableConfigs: EnableConfiguration[] = [
{
name: 'input',
key: 'input',
@@ -89,7 +101,7 @@ const sfTraceEnableConfigs: Array<EnableConfiguration> = [
},
];
const sfTraceSelectionConfigs: Array<SelectionConfiguration> = [
const sfTraceSelectionConfigs: SelectionConfiguration[] = [
{
key: 'sfbuffersize',
name: 'buffer size (KB)',

View File

@@ -17,8 +17,8 @@ import {PersistentStoreProxy} from 'common/persistent_store_proxy';
import {TraceConfigurationMap, TRACES} from './trace_collection_utils';
export class TracingConfig {
public requestedTraces: string[] = [];
public requestedDumps: string[] = [];
requestedTraces: string[] = [];
requestedDumps: string[] = [];
private storage: Storage | undefined;
private tracingConfig: TraceConfigurationMap | undefined;
@@ -28,7 +28,7 @@ export class TracingConfig {
return setTracesInstance;
}
public initialize(storage: Storage) {
initialize(storage: Storage) {
this.storage = storage;
this.tracingConfig = PersistentStoreProxy.new<TraceConfigurationMap>(
'TracingSettings',
@@ -55,7 +55,7 @@ export class TracingConfig {
);
}
public setTracingConfigForAvailableTraces(isWaylandAvailable = false) {
setTracingConfigForAvailableTraces(isWaylandAvailable = false) {
const availableTracesConfig = TRACES['default'];
if (isWaylandAvailable) {
Object.assign(availableTracesConfig, TRACES['arc']);
@@ -63,11 +63,11 @@ export class TracingConfig {
this.setTracingConfig(availableTracesConfig);
}
public tracingConfigIsSet(): boolean {
tracingConfigIsSet(): boolean {
return this.tracingConfig !== undefined;
}
public getTracingConfig(): TraceConfigurationMap {
getTracingConfig(): TraceConfigurationMap {
if (this.tracingConfig === undefined) {
throw Error('Tracing config not initialized yet');
}
@@ -85,7 +85,7 @@ export class TracingConfig {
);
}
public getDumpConfig(): TraceConfigurationMap {
getDumpConfig(): TraceConfigurationMap {
if (this.dumpConfig === undefined) {
throw Error('Dump config not initialized yet');
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
export default class Chip {
export class Chip {
short: string;
long: string;
type: string;

View File

@@ -20,9 +20,9 @@ import {HierarchyTreeNode, PropertiesTreeNode} from 'viewers/common/ui_tree_util
import {UserOptions} from 'viewers/common/user_options';
export class ImeUiData {
dependencies: Array<TraceType>;
highlightedItems: Array<string> = [];
pinnedItems: Array<HierarchyTreeNode> = [];
dependencies: TraceType[];
highlightedItems: string[] = [];
pinnedItems: HierarchyTreeNode[] = [];
hierarchyUserOptions: UserOptions = {};
propertiesUserOptions: UserOptions = {};
tree: HierarchyTreeNode | null = null;
@@ -30,7 +30,7 @@ export class ImeUiData {
hierarchyTableProperties: TableProperties | null = null;
additionalProperties: ImeAdditionalProperties | null = null;
constructor(dependencies?: Array<TraceType>) {
constructor(dependencies?: TraceType[]) {
this.dependencies = dependencies ?? [];
}
}

View File

@@ -17,9 +17,9 @@ import {FilterType, TreeUtils} from 'common/tree_utils';
import {WindowContainer} from 'trace/flickerlib/common';
import {Layer} from 'trace/flickerlib/layers/Layer';
import {LayerTraceEntry} from 'trace/flickerlib/layers/LayerTraceEntry';
import Activity from 'trace/flickerlib/windows/Activity';
import {Activity} from 'trace/flickerlib/windows/Activity';
import {WindowManagerState} from 'trace/flickerlib/windows/WindowManagerState';
import WindowState from 'trace/flickerlib/windows/WindowState';
import {WindowState} from 'trace/flickerlib/windows/WindowState';
class ProcessedWindowManagerState {
constructor(
@@ -49,9 +49,7 @@ class ImeLayers {
}
class ImeUtils {
public static processWindowManagerTraceEntry(
entry: WindowManagerState
): ProcessedWindowManagerState {
static processWindowManagerTraceEntry(entry: WindowManagerState): ProcessedWindowManagerState {
const displayContent = entry.root.children[0];
return new ProcessedWindowManagerState(
@@ -60,16 +58,16 @@ class ImeUtils {
entry.focusedApp,
entry.focusedWindow,
entry.focusedActivity,
this.isInputMethodVisible(displayContent),
this.getImeControlTargetProperty(displayContent.proto),
this.getImeInputTargetProperty(displayContent.proto),
this.getImeLayeringTargetProperty(displayContent.proto),
ImeUtils.isInputMethodVisible(displayContent),
ImeUtils.getImeControlTargetProperty(displayContent.proto),
ImeUtils.getImeInputTargetProperty(displayContent.proto),
ImeUtils.getImeLayeringTargetProperty(displayContent.proto),
displayContent.proto.imeInsetsSourceProvider,
entry.proto
);
}
public static getImeLayers(
static getImeLayers(
entry: LayerTraceEntry,
processedWindowManagerState: ProcessedWindowManagerState
): ImeLayers | undefined {
@@ -91,12 +89,12 @@ class ImeUtils {
// we want to see both ImeContainer and IME-snapshot if there are
// cases where both exist
const taskLayerOfImeContainer = this.findAncestorTaskLayerOfImeLayer(
const taskLayerOfImeContainer = ImeUtils.findAncestorTaskLayerOfImeLayer(
entry,
TreeUtils.makeNodeFilter('ImeContainer')
);
const taskLayerOfImeSnapshot = this.findAncestorTaskLayerOfImeLayer(
const taskLayerOfImeSnapshot = ImeUtils.findAncestorTaskLayerOfImeLayer(
entry,
TreeUtils.makeNodeFilter('IME-snapshot')
);
@@ -111,7 +109,7 @@ class ImeUtils {
);
}
public static transformInputConnectionCall(entry: any) {
static transformInputConnectionCall(entry: any) {
const obj = Object.assign({}, entry);
if (obj.inputConnectionCall) {
Object.getOwnPropertyNames(obj.inputConnectionCall).forEach((name) => {
@@ -132,7 +130,7 @@ class ImeUtils {
}
const isTaskLayer = TreeUtils.makeNodeFilter('Task, ImePlaceholder');
const taskLayer = <Layer>TreeUtils.findAncestorNode(imeLayer, isTaskLayer);
const taskLayer = TreeUtils.findAncestorNode(imeLayer, isTaskLayer) as Layer;
if (!taskLayer) {
return undefined;
}
@@ -143,17 +141,17 @@ class ImeUtils {
private static getImeControlTargetProperty(displayContentProto: any): any {
const POSSIBLE_NAMES = ['inputMethodControlTarget', 'imeControlTarget'];
return this.findAnyPropertyWithMatchingName(displayContentProto, POSSIBLE_NAMES);
return ImeUtils.findAnyPropertyWithMatchingName(displayContentProto, POSSIBLE_NAMES);
}
private static getImeInputTargetProperty(displayContentProto: any): any {
const POSSIBLE_NAMES = ['inputMethodInputTarget', 'imeInputTarget'];
return this.findAnyPropertyWithMatchingName(displayContentProto, POSSIBLE_NAMES);
return ImeUtils.findAnyPropertyWithMatchingName(displayContentProto, POSSIBLE_NAMES);
}
private static getImeLayeringTargetProperty(displayContentProto: any): any {
const POSSIBLE_NAMES = ['inputMethodTarget', 'imeLayeringTarget'];
return this.findAnyPropertyWithMatchingName(displayContentProto, POSSIBLE_NAMES);
return ImeUtils.findAnyPropertyWithMatchingName(displayContentProto, POSSIBLE_NAMES);
}
private static findAnyPropertyWithMatchingName(object: any, possible_names: string[]): any {
@@ -163,10 +161,11 @@ class ImeUtils {
private static isInputMethodVisible(displayContent: WindowContainer): boolean {
const isInputMethod = TreeUtils.makeNodeFilter('InputMethod');
const inputMethodWindowOrLayer = <WindowContainer>(
TreeUtils.findDescendantNode(displayContent, isInputMethod)
);
return inputMethodWindowOrLayer?.isVisible == true;
const inputMethodWindowOrLayer = TreeUtils.findDescendantNode(
displayContent,
isInputMethod
) as WindowContainer;
return inputMethodWindowOrLayer?.isVisible === true;
}
}

View File

@@ -31,7 +31,7 @@ type NotifyImeViewCallbackType = (uiData: ImeUiData) => void;
export abstract class PresenterInputMethod {
constructor(
notifyViewCallback: NotifyImeViewCallbackType,
dependencies: Array<TraceType>,
dependencies: TraceType[],
private storage: Storage
) {
this.notifyViewCallback = notifyViewCallback;
@@ -40,10 +40,10 @@ export abstract class PresenterInputMethod {
this.notifyViewCallback(this.uiData);
}
public updatePinnedItems(pinnedItem: HierarchyTreeNode) {
updatePinnedItems(pinnedItem: HierarchyTreeNode) {
const pinnedId = `${pinnedItem.id}`;
if (this.pinnedItems.map((item) => `${item.id}`).includes(pinnedId)) {
this.pinnedItems = this.pinnedItems.filter((pinned) => `${pinned.id}` != pinnedId);
this.pinnedItems = this.pinnedItems.filter((pinned) => `${pinned.id}` !== pinnedId);
} else {
this.pinnedItems.push(pinnedItem);
}
@@ -52,9 +52,9 @@ export abstract class PresenterInputMethod {
this.notifyViewCallback(this.uiData);
}
public updateHighlightedItems(id: string) {
updateHighlightedItems(id: string) {
if (this.highlightedItems.includes(id)) {
this.highlightedItems = this.highlightedItems.filter((hl) => hl != id);
this.highlightedItems = this.highlightedItems.filter((hl) => hl !== id);
} else {
this.highlightedItems = []; //if multi-select surfaces implemented, remove this line
this.highlightedItems.push(id);
@@ -63,37 +63,37 @@ export abstract class PresenterInputMethod {
this.notifyViewCallback(this.uiData);
}
public updateHierarchyTree(userOptions: UserOptions) {
updateHierarchyTree(userOptions: UserOptions) {
this.hierarchyUserOptions = userOptions;
this.uiData.hierarchyUserOptions = this.hierarchyUserOptions;
this.uiData.tree = this.generateTree();
this.notifyViewCallback(this.uiData);
}
public filterHierarchyTree(filterString: string) {
filterHierarchyTree(filterString: string) {
this.hierarchyFilter = TreeUtils.makeNodeFilter(filterString);
this.uiData.tree = this.generateTree();
this.notifyViewCallback(this.uiData);
}
public updatePropertiesTree(userOptions: UserOptions) {
updatePropertiesTree(userOptions: UserOptions) {
this.propertiesUserOptions = userOptions;
this.uiData.propertiesUserOptions = this.propertiesUserOptions;
this.updateSelectedTreeUiData();
}
public filterPropertiesTree(filterString: string) {
filterPropertiesTree(filterString: string) {
this.propertiesFilter = TreeUtils.makeNodeFilter(filterString);
this.updateSelectedTreeUiData();
}
public newPropertiesTree(selectedItem: HierarchyTreeNode) {
newPropertiesTree(selectedItem: HierarchyTreeNode) {
this.additionalPropertyEntry = null;
this.selectedHierarchyTree = selectedItem;
this.updateSelectedTreeUiData();
}
public newAdditionalPropertiesTree(selectedItem: any) {
newAdditionalPropertiesTree(selectedItem: any) {
this.selectedHierarchyTree = new HierarchyTreeNode(
selectedItem.name,
'AdditionalProperty',
@@ -109,7 +109,7 @@ export abstract class PresenterInputMethod {
this.updateSelectedTreeUiData();
}
public notifyCurrentTraceEntries(entries: Map<TraceType, [any, any]>) {
notifyCurrentTraceEntries(entries: Map<TraceType, [any, any]>) {
this.uiData = new ImeUiData(this.dependencies);
this.uiData.hierarchyUserOptions = this.hierarchyUserOptions;
this.uiData.propertiesUserOptions = this.propertiesUserOptions;
@@ -185,7 +185,7 @@ export abstract class PresenterInputMethod {
}
private updatePinnedIds(newId: string) {
if (this.pinnedIds.includes(newId)) {
this.pinnedIds = this.pinnedIds.filter((pinned) => pinned != newId);
this.pinnedIds = this.pinnedIds.filter((pinned) => pinned !== newId);
} else {
this.pinnedIds.push(newId);
}
@@ -203,14 +203,14 @@ export abstract class PresenterInputMethod {
private hierarchyFilter: FilterType = TreeUtils.makeNodeFilter('');
private propertiesFilter: FilterType = TreeUtils.makeNodeFilter('');
private pinnedItems: Array<HierarchyTreeNode> = [];
private pinnedIds: Array<string> = [];
private pinnedItems: HierarchyTreeNode[] = [];
private pinnedIds: string[] = [];
private selectedHierarchyTree: HierarchyTreeNode | null = null;
readonly notifyViewCallback: NotifyImeViewCallbackType;
protected readonly dependencies: Array<TraceType>;
protected readonly dependencies: TraceType[];
protected uiData: ImeUiData;
protected highlightedItems: Array<string> = [];
protected highlightedItems: string[] = [];
protected entry: TraceTreeNode | null = null;
protected additionalPropertyEntry: TraceTreeNode | null = null;
protected hierarchyUserOptions: UserOptions = PersistentStoreProxy.new<UserOptions>(

View File

@@ -17,7 +17,7 @@
import {PropertiesTreeNode} from './ui_tree_utils';
class PropertiesTreeGenerator {
public generate(key: string, value: any): PropertiesTreeNode {
generate(key: string, value: any): PropertiesTreeNode {
if (this.isLeaf(value)) {
return {
propertyKey: key,
@@ -35,7 +35,7 @@ class PropertiesTreeGenerator {
return {
propertyKey: key,
children: children,
children,
};
}

View File

@@ -13,6 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export type TableProperties = {
export interface TableProperties {
[key: string]: string | boolean | undefined;
};
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
import {FilterType, TreeNode} from 'common/tree_utils';
import ObjectFormatter from 'trace/flickerlib/ObjectFormatter';
import {ObjectFormatter} from 'trace/flickerlib/ObjectFormatter';
import {TraceTreeNode} from 'trace/trace_tree_node';
import {
GPU_CHIP,
@@ -49,42 +49,42 @@ export class TreeGenerator {
private isModified?: IsModifiedCallbackType;
private newMapping: Map<string, TraceTreeNode> | null = null;
private oldMapping: Map<string, TraceTreeNode> | null = null;
private readonly pinnedIds: Array<string>;
private pinnedItems: Array<HierarchyTreeNode> = [];
private relZParentIds: Array<string> = [];
private flattenedChildren: Array<HierarchyTreeNode> = [];
private readonly pinnedIds: string[];
private pinnedItems: HierarchyTreeNode[] = [];
private relZParentIds: string[] = [];
private flattenedChildren: HierarchyTreeNode[] = [];
constructor(inputEntry: TraceTreeNode, filter: FilterType, pinnedIds?: Array<string>) {
constructor(inputEntry: TraceTreeNode, filter: FilterType, pinnedIds?: string[]) {
this.inputEntry = inputEntry;
this.filter = filter;
this.pinnedIds = pinnedIds ?? [];
}
public setIsOnlyVisibleView(enabled: boolean): TreeGenerator {
setIsOnlyVisibleView(enabled: boolean): TreeGenerator {
this.isOnlyVisibleView = enabled;
return this;
}
public setIsSimplifyNames(enabled: boolean): TreeGenerator {
setIsSimplifyNames(enabled: boolean): TreeGenerator {
this.isSimplifyNames = enabled;
return this;
}
public setIsFlatView(enabled: boolean): TreeGenerator {
setIsFlatView(enabled: boolean): TreeGenerator {
this.isFlatView = enabled;
return this;
}
public generateTree(): HierarchyTreeNode | null {
generateTree(): HierarchyTreeNode | null {
return this.getCustomizedTree(this.inputEntry);
}
public compareWith(previousEntry: TraceTreeNode | null): TreeGenerator {
compareWith(previousEntry: TraceTreeNode | null): TreeGenerator {
this.previousEntry = previousEntry;
return this;
}
public withUniqueNodeId(getNodeId?: GetNodeIdCallbackType): TreeGenerator {
withUniqueNodeId(getNodeId?: GetNodeIdCallbackType): TreeGenerator {
this.getNodeId = (node: TraceTreeNode | null) => {
const id = getNodeId ? getNodeId(node) : this.defaultNodeIdCallback(node);
if (id === null || id === undefined) {
@@ -96,12 +96,12 @@ export class TreeGenerator {
return this;
}
public withModifiedCheck(isModified?: IsModifiedCallbackType): TreeGenerator {
withModifiedCheck(isModified?: IsModifiedCallbackType): TreeGenerator {
this.isModified = isModified ?? this.defaultModifiedCheck;
return this;
}
public generateFinalTreeWithDiff(): HierarchyTreeNode | null {
generateFinalTreeWithDiff(): HierarchyTreeNode | null {
this.newMapping = this.generateIdToNodeMapping(this.inputEntry);
this.oldMapping = this.previousEntry ? this.generateIdToNodeMapping(this.previousEntry) : null;
@@ -135,11 +135,11 @@ export class TreeGenerator {
return Object.freeze(newTree);
}
public getPinnedItems(): Array<HierarchyTreeNode> {
getPinnedItems(): HierarchyTreeNode[] {
return this.pinnedItems;
}
private flattenChildren(children: Array<HierarchyTreeNode>) {
private flattenChildren(children: HierarchyTreeNode[]) {
for (let i = 0; i < children.length; i++) {
const child = children[i];
const childIsVisibleNode =
@@ -184,11 +184,11 @@ export class TreeGenerator {
}
private addChips(tree: HierarchyTreeNode): HierarchyTreeNode {
if (tree.hwcCompositionType == HwcCompositionType.CLIENT) {
if (tree.hwcCompositionType === HwcCompositionType.CLIENT) {
tree.chips.push(GPU_CHIP);
} else if (
tree.hwcCompositionType == HwcCompositionType.DEVICE ||
tree.hwcCompositionType == HwcCompositionType.SOLID_COLOR
tree.hwcCompositionType === HwcCompositionType.DEVICE ||
tree.hwcCompositionType === HwcCompositionType.SOLID_COLOR
) {
tree.chips.push(HWC_CHIP);
}
@@ -323,7 +323,7 @@ export class TreeGenerator {
oldTree: TraceTreeNode | null,
newTreeSiblings: Array<TraceTreeNode | null>,
oldTreeSiblings: Array<TraceTreeNode | null>
): Array<TraceTreeNode> {
): TraceTreeNode[] {
const diffTrees = [];
// NOTE: A null ID represents a non existent node.
if (!this.getNodeId) {
@@ -417,7 +417,7 @@ export class TreeGenerator {
private visitChildren(
newTree: TraceTreeNode | null,
oldTree: TraceTreeNode | null
): Array<TraceTreeNode> {
): TraceTreeNode[] {
// Recursively traverse all children of new and old tree.
const diffChildren = [];
const numOfChildren = Math.max(newTree?.children?.length ?? 0, oldTree?.children?.length ?? 0);

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
import {FilterType, TreeNode} from 'common/tree_utils';
import ObjectFormatter from 'trace/flickerlib/ObjectFormatter';
import {ObjectFormatter} from 'trace/flickerlib/ObjectFormatter';
import {TraceTreeNode} from 'trace/trace_tree_node';
import {
@@ -58,22 +58,22 @@ export class TreeTransformer {
this.setTransformerOptions({});
}
public setOnlyProtoDump(onlyProto: boolean): TreeTransformer {
setOnlyProtoDump(onlyProto: boolean): TreeTransformer {
this.onlyProtoDump = onlyProto;
return this;
}
public setIsShowDefaults(enabled: boolean): TreeTransformer {
setIsShowDefaults(enabled: boolean): TreeTransformer {
this.isShowDefaults = enabled;
return this;
}
public setIsShowDiff(enabled: boolean): TreeTransformer {
setIsShowDiff(enabled: boolean): TreeTransformer {
this.isShowDiff = enabled;
return this;
}
public setTransformerOptions(options: TreeTransformerOptions): TreeTransformer {
setTransformerOptions(options: TreeTransformerOptions): TreeTransformer {
this.options = options;
if (!this.options.formatter) {
this.options.formatter = this.formatProto;
@@ -81,7 +81,7 @@ export class TreeTransformer {
return this;
}
public setProperties(currentEntry: TraceTreeNode | null): TreeTransformer {
setProperties(currentEntry: TraceTreeNode | null): TreeTransformer {
const currFlickerItem = this.getOriginalFlickerItem(currentEntry, this.stableId);
const target = currFlickerItem ? currFlickerItem.obj ?? currFlickerItem : null;
ObjectFormatter.displayDefaults = this.isShowDefaults;
@@ -91,7 +91,7 @@ export class TreeTransformer {
return this;
}
public setDiffProperties(previousEntry: TraceTreeNode | null): TreeTransformer {
setDiffProperties(previousEntry: TraceTreeNode | null): TreeTransformer {
if (this.isShowDiff) {
const prevFlickerItem = this.findFlickerItem(previousEntry, this.stableId);
const target = prevFlickerItem ? prevFlickerItem.obj ?? prevFlickerItem : null;
@@ -102,10 +102,7 @@ export class TreeTransformer {
return this;
}
public getOriginalFlickerItem(
entry: TraceTreeNode | null,
stableId: string
): TraceTreeNode | null {
getOriginalFlickerItem(entry: TraceTreeNode | null, stableId: string): TraceTreeNode | null {
return this.findFlickerItem(entry, stableId);
}
@@ -151,7 +148,7 @@ export class TreeTransformer {
return null;
}
public transform(): PropertiesTreeNode {
transform(): PropertiesTreeNode {
const {formatter} = this.options!;
if (!formatter) {
throw new Error('Missing formatter, please set with setOptions()');
@@ -249,7 +246,7 @@ export class TreeTransformer {
}
let transformedProperties: any;
if (children.length == 1 && children[0].children?.length == 0 && !children[0].combined) {
if (children.length === 1 && children[0].children?.length === 0 && !children[0].combined) {
// Merge leaf key value pairs.
const child = children[0];
@@ -276,7 +273,7 @@ export class TreeTransformer {
const diffType = this.getDiff(name, compareWithName);
transformedProperties.diffType = diffType;
if (diffType == DiffType.DELETED) {
if (diffType === DiffType.DELETED) {
transformedProperties.name = compareWithName;
}
}
@@ -346,7 +343,7 @@ export class TreeTransformer {
private filterMatches(item: PropertiesDump | null): boolean {
//TODO: fix PropertiesDump type. What is it? Why does it declare only a "key" property and yet it is used as a TreeNode?
return this.filter(<TreeNode>item) ?? false;
return this.filter(item as TreeNode) ?? false;
}
private transformProperties(
@@ -357,27 +354,29 @@ export class TreeTransformer {
const transformedProperties: PropertiesTreeNode = {
properties: {},
};
let formatted = undefined;
if (skip && skip.includes(properties)) {
// skip
} else if ((formatted = formatter(properties))) {
return transformedProperties; // skip
}
const formatted = formatter(properties);
if (formatted) {
// Obj has been formatted into a terminal node — has no children.
transformedProperties.properties[formatted] = new Terminal();
} else if (Array.isArray(properties)) {
properties.forEach((e, i) => {
transformedProperties.properties['' + i] = e;
});
} else if (typeof properties == 'string') {
} else if (typeof properties === 'string') {
// Object is a primitive type — has no children. Set to terminal
// to differentiate between null object and Terminal element.
transformedProperties.properties[properties] = new Terminal();
} else if (typeof properties == 'number' || typeof properties == 'boolean') {
} else if (typeof properties === 'number' || typeof properties === 'boolean') {
// Similar to above — primitive type node has no children.
transformedProperties.properties['' + properties] = new Terminal();
} else if (properties && typeof properties == 'object') {
} else if (properties && typeof properties === 'object') {
// Empty objects
if (Object.keys(properties).length == 0) {
if (Object.keys(properties).length === 0) {
transformedProperties.properties['[empty]'] = new Terminal();
} else {
// Non empty objects
@@ -400,7 +399,7 @@ export class TreeTransformer {
return DiffType.ADDED;
} else if (this.isTerminal(val) && compareVal) {
return DiffType.DELETED;
} else if (compareVal != val) {
} else if (compareVal !== val) {
return DiffType.MODIFIED;
} else {
return DiffType.NONE;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
import Chip from './chip';
import {Chip} from './chip';
export type UiTreeNode = HierarchyTreeNode | PropertiesTreeNode;
@@ -78,21 +78,21 @@ export const DiffType = {
export class Terminal {}
export class UiTreeUtils {
public static diffClass(item: UiTreeNode): string {
static diffClass(item: UiTreeNode): string {
const diffType = item.diffType;
return diffType ?? '';
}
public static isHighlighted(item: UiTreeNode, highlightedItems: Array<string>) {
static isHighlighted(item: UiTreeNode, highlightedItems: string[]) {
return item instanceof HierarchyTreeNode && highlightedItems.includes(`${item.stableId}`);
}
public static isVisibleNode(kind: string, type?: string) {
static isVisibleNode(kind: string, type?: string) {
return kind === 'WindowState' || kind === 'Activity' || type?.includes('Layer');
}
public static isParentNode(kind: string) {
return this.PARENT_NODE_KINDS.includes(kind);
static isParentNode(kind: string) {
return UiTreeUtils.PARENT_NODE_KINDS.includes(kind);
}
private static readonly PARENT_NODE_KINDS = [

View File

@@ -26,12 +26,12 @@ abstract class ViewerInputMethod implements Viewer {
this.addViewerEventListeners();
}
public notifyCurrentTraceEntries(entries: Map<TraceType, any>): void {
notifyCurrentTraceEntries(entries: Map<TraceType, any>): void {
this.presenter.notifyCurrentTraceEntries(entries);
}
public abstract getViews(): View[];
public abstract getDependencies(): TraceType[];
abstract getViews(): View[];
abstract getDependencies(): TraceType[];
protected imeUiCallback = (uiData: ImeUiData) => {
// Angular does not deep watch @Input properties. Clearing inputData to null before repopulating

View File

@@ -129,19 +129,19 @@ export class HierarchyComponent {
@Input() tree!: HierarchyTreeNode | null;
@Input() tableProperties?: TableProperties | null;
@Input() dependencies: Array<TraceType> = [];
@Input() highlightedItems: Array<string> = [];
@Input() pinnedItems: Array<HierarchyTreeNode> = [];
@Input() dependencies: TraceType[] = [];
@Input() highlightedItems: string[] = [];
@Input() pinnedItems: HierarchyTreeNode[] = [];
@Input() store!: PersistentStore;
@Input() userOptions: UserOptions = {};
constructor(@Inject(ElementRef) private elementRef: ElementRef) {}
public isFlattened() {
isFlattened() {
return this.userOptions['flat']?.enabled;
}
public onPinnedNodeClick(event: MouseEvent, pinnedItem: HierarchyTreeNode) {
onPinnedNodeClick(event: MouseEvent, pinnedItem: HierarchyTreeNode) {
event.preventDefault();
if (window.getSelection()?.type === 'range') {
return;
@@ -150,7 +150,7 @@ export class HierarchyComponent {
this.selectedTreeChange(pinnedItem);
}
public updateTree() {
updateTree() {
const event: CustomEvent = new CustomEvent(ViewerEvents.HierarchyUserOptionsChange, {
bubbles: true,
detail: {userOptions: this.userOptions},
@@ -158,7 +158,7 @@ export class HierarchyComponent {
this.elementRef.nativeElement.dispatchEvent(event);
}
public filterTree() {
filterTree() {
const event: CustomEvent = new CustomEvent(ViewerEvents.HierarchyFilterChange, {
bubbles: true,
detail: {filterString: this.filterString},
@@ -166,7 +166,7 @@ export class HierarchyComponent {
this.elementRef.nativeElement.dispatchEvent(event);
}
public highlightedItemChange(newId: string) {
highlightedItemChange(newId: string) {
const event: CustomEvent = new CustomEvent(ViewerEvents.HighlightedChange, {
bubbles: true,
detail: {id: newId},
@@ -174,7 +174,7 @@ export class HierarchyComponent {
this.elementRef.nativeElement.dispatchEvent(event);
}
public selectedTreeChange(item: UiTreeNode) {
selectedTreeChange(item: UiTreeNode) {
if (!(item instanceof HierarchyTreeNode)) {
return;
}
@@ -185,7 +185,7 @@ export class HierarchyComponent {
this.elementRef.nativeElement.dispatchEvent(event);
}
public pinnedItemChange(item: UiTreeNode) {
pinnedItemChange(item: UiTreeNode) {
if (!(item instanceof HierarchyTreeNode)) {
return;
}

View File

@@ -321,25 +321,25 @@ import {ViewerEvents} from 'viewers/common/viewer_events';
export class ImeAdditionalPropertiesComponent {
@Input() additionalProperties!: ImeAdditionalProperties;
@Input() isImeManagerService?: boolean;
@Input() highlightedItems: Array<string> = [];
@Input() highlightedItems: string[] = [];
constructor(@Inject(ElementRef) private elementRef: ElementRef) {}
public isHighlighted(item: any) {
isHighlighted(item: any) {
return UiTreeUtils.isHighlighted(item, this.highlightedItems);
}
public formatProto(item: any) {
formatProto(item: any) {
if (item?.prettyPrint) {
return item.prettyPrint();
}
}
public wmProtoOrNull() {
wmProtoOrNull() {
return this.additionalProperties.wm?.proto;
}
public wmInsetsSourceProviderOrNull() {
wmInsetsSourceProviderOrNull() {
return this.additionalProperties.wm?.protoImeInsetsSourceProvider
? Object.assign(
{name: 'Ime Insets Source Provider'},
@@ -348,56 +348,56 @@ export class ImeAdditionalPropertiesComponent {
: null;
}
public wmControlTargetFrameOrNull() {
wmControlTargetFrameOrNull() {
return (
this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider
?.controlTarget?.windowFrames?.frame || 'null'
);
}
public wmInsetsSourceProviderPositionOrNull() {
wmInsetsSourceProviderPositionOrNull() {
return (
this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider?.control
?.position || 'null'
);
}
public wmInsetsSourceProviderIsLeashReadyOrNull() {
wmInsetsSourceProviderIsLeashReadyOrNull() {
return (
this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider
?.isLeashReadyForDispatching || 'null'
);
}
public wmInsetsSourceProviderControllableOrNull() {
wmInsetsSourceProviderControllableOrNull() {
return (
this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider
?.controllable || 'null'
);
}
public wmInsetsSourceProviderSourceFrameOrNull() {
wmInsetsSourceProviderSourceFrameOrNull() {
return (
this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider?.source
?.frame || 'null'
);
}
public wmInsetsSourceProviderSourceVisibleOrNull() {
wmInsetsSourceProviderSourceVisibleOrNull() {
return (
this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider?.source
?.visible || 'null'
);
}
public wmInsetsSourceProviderSourceVisibleFrameOrNull() {
wmInsetsSourceProviderSourceVisibleFrameOrNull() {
return (
this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider?.source
?.visibleFrame || 'null'
);
}
public wmImeControlTargetOrNull() {
wmImeControlTargetOrNull() {
return this.additionalProperties?.wm?.protoImeControlTarget
? Object.assign(
{name: 'IME Control Target'},
@@ -406,26 +406,26 @@ export class ImeAdditionalPropertiesComponent {
: null;
}
public wmImeControlTargetTitleOrNull() {
wmImeControlTargetTitleOrNull() {
return (
this.additionalProperties?.wm?.protoImeControlTarget?.windowContainer?.identifier?.title ||
'null'
);
}
public wmImeInputTargetOrNull() {
wmImeInputTargetOrNull() {
return this.additionalProperties?.wm?.protoImeInputTarget
? Object.assign({name: 'IME Input Target'}, this.additionalProperties.wm.protoImeInputTarget)
: null;
}
public wmImeInputTargetTitleOrNull() {
wmImeInputTargetTitleOrNull() {
return (
this.additionalProperties?.wm?.protoImeInputTarget?.windowContainer?.identifier?.title ||
'null'
);
}
public wmImeLayeringTargetOrNull() {
wmImeLayeringTargetOrNull() {
return this.additionalProperties?.wm?.protoImeLayeringTarget
? Object.assign(
{name: 'IME Layering Target'},
@@ -434,22 +434,22 @@ export class ImeAdditionalPropertiesComponent {
: null;
}
public wmImeLayeringTargetTitleOrNull() {
wmImeLayeringTargetTitleOrNull() {
return (
this.additionalProperties?.wm?.protoImeLayeringTarget?.windowContainer?.identifier?.title ||
'null'
);
}
public sfImeContainerScreenBoundsOrNull() {
sfImeContainerScreenBoundsOrNull() {
return this.additionalProperties.sf?.inputMethodSurface?.screenBounds || 'null';
}
public sfImeContainerRectOrNull() {
sfImeContainerRectOrNull() {
return this.additionalProperties.sf?.inputMethodSurface?.rect || 'null';
}
public isAllPropertiesNull() {
isAllPropertiesNull() {
if (this.isImeManagerService) {
return !this.additionalProperties.wm;
} else {
@@ -457,7 +457,7 @@ export class ImeAdditionalPropertiesComponent {
}
}
public onClickShowInPropertiesPanel(item: any, name?: string) {
onClickShowInPropertiesPanel(item: any, name?: string) {
if (item.id) {
this.updateHighlightedItems(item.id);
} else {
@@ -475,7 +475,7 @@ export class ImeAdditionalPropertiesComponent {
private updateAdditionalPropertySelected(item: any, name?: string) {
const itemWrapper = {
name: name,
name,
proto: item,
};
const event: CustomEvent = new CustomEvent(ViewerEvents.AdditionalPropertySelected, {

View File

@@ -127,7 +127,7 @@ export class PropertiesComponent {
constructor(@Inject(ElementRef) private elementRef: ElementRef) {}
public filterTree() {
filterTree() {
const event: CustomEvent = new CustomEvent(ViewerEvents.PropertiesFilterChange, {
bubbles: true,
detail: {filterString: this.filterString},
@@ -135,7 +135,7 @@ export class PropertiesComponent {
this.elementRef.nativeElement.dispatchEvent(event);
}
public updateTree() {
updateTree() {
const event: CustomEvent = new CustomEvent(ViewerEvents.PropertiesUserOptionsChange, {
bubbles: true,
detail: {userOptions: this.userOptions},
@@ -143,7 +143,7 @@ export class PropertiesComponent {
this.elementRef.nativeElement.dispatchEvent(event);
}
public showNode(item: any) {
showNode(item: any) {
return (
!(item instanceof Terminal) &&
!(item.name instanceof Terminal) &&
@@ -151,7 +151,7 @@ export class PropertiesComponent {
);
}
public isLeaf(item: any) {
isLeaf(item: any) {
return (
!item.children ||
item.children.length === 0 ||
@@ -159,7 +159,7 @@ export class PropertiesComponent {
);
}
public itemIsSelected() {
itemIsSelected() {
return this.selectedFlickerItem && Object.keys(this.selectedFlickerItem).length > 0;
}
}

View File

@@ -280,26 +280,26 @@ import {Layer} from 'trace/flickerlib/common';
export class PropertyGroupsComponent {
@Input() item!: Layer;
public hasInputChannel() {
hasInputChannel() {
return this.item.proto?.inputWindowInfo;
}
public getDestinationFrame() {
getDestinationFrame() {
const frame = this.item.proto?.destinationFrame;
if (frame) {
return ` left: ${frame.left}, top: ${frame.top}, right: ${frame.right}, bottom: ${frame.bottom}`;
} else return '';
}
public hasIgnoreDestinationFrame() {
hasIgnoreDestinationFrame() {
return (this.item.flags & 0x400) === 0x400;
}
public formatFloat(num: number) {
formatFloat(num: number) {
return Math.round(num * 100) / 100;
}
public summary(): TreeSummary {
summary(): TreeSummary {
const summary = [];
if (this.item?.visibilityReason?.length > 0) {

View File

@@ -114,7 +114,7 @@ export class Canvas {
this.labelRenderer.render(this.scene, this.camera);
}
public getClickedRectId(x: number, y: number, z: number): undefined | string {
getClickedRectId(x: number, y: number, z: number): undefined | string {
const clickPosition = new THREE.Vector3(x, y, z);
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(clickPosition, this.camera!);
@@ -231,7 +231,7 @@ export class Canvas {
rectGeometry,
new THREE.MeshBasicMaterial({
color: this.getColor(rect),
opacity: opacity,
opacity,
transparent: true,
})
);
@@ -279,30 +279,28 @@ export class Canvas {
}
private getColor(rect: Rect3D): THREE.Color {
let color: THREE.Color = Canvas.RECT_COLOR_HIGHLIGHTED;
switch (rect.colorType) {
case ColorType.VISIBLE: {
// green (darkness depends on z order)
const red = ((200 - 45) * rect.darkFactor + 45) / 255;
const green = ((232 - 182) * rect.darkFactor + 182) / 255;
const blue = ((183 - 44) * rect.darkFactor + 44) / 255;
color = new THREE.Color(red, green, blue);
break;
return new THREE.Color(red, green, blue);
}
case ColorType.NOT_VISIBLE: {
// gray (darkness depends on z order)
const lower = 120;
const upper = 220;
const darkness = ((upper - lower) * rect.darkFactor + lower) / 255;
color = new THREE.Color(darkness, darkness, darkness);
break;
return new THREE.Color(darkness, darkness, darkness);
}
case ColorType.HIGHLIGHTED: {
color = Canvas.RECT_COLOR_HIGHLIGHTED;
break;
return Canvas.RECT_COLOR_HIGHLIGHTED;
}
default: {
throw new Error(`Unexpected color type: ${rect.colorType}`);
}
}
return color;
}
private createRectBorders(rect: Rect3D, rectGeometry: THREE.ShapeGeometry): THREE.LineSegments {

View File

@@ -134,7 +134,7 @@ class Mapper3D {
const boundingBox = this.computeBoundingBox(rects3d, labels3d);
const scene: Scene3D = {
boundingBox: boundingBox,
boundingBox,
camera: {
rotationFactor: this.cameraRotationFactor,
zoomFactor: this.zoomFactor,
@@ -148,7 +148,7 @@ class Mapper3D {
}
private selectRectsToDraw(rects: Rectangle[]): Rectangle[] {
rects = rects.filter((rect) => rect.displayId == this.currentDisplayId);
rects = rects.filter((rect) => rect.displayId === this.currentDisplayId);
if (this.showOnlyVisibleMode) {
rects = rects.filter((rect) => rect.isVisible || rect.isDisplay);
@@ -191,16 +191,16 @@ class Mapper3D {
topLeft: {
x: rect2d.topLeft.x,
y: rect2d.topLeft.y,
z: z,
z,
},
bottomRight: {
x: rect2d.bottomRight.x,
y: rect2d.bottomRight.y,
z: z,
z,
},
isOversized: false,
cornerRadius: rect2d.cornerRadius,
darkFactor: darkFactor,
darkFactor,
colorType: this.getColorType(rect2d),
isClickable: rect2d.isClickable,
transform: this.getTransform(rect2d),
@@ -346,7 +346,7 @@ class Mapper3D {
linePoints: [lineStart, lineEnd],
textCenter: lineEnd,
text: rect2d.label,
isHighlighted: isHighlighted,
isHighlighted,
rectId: rect2d.id,
};
labels3d.push(label3d);
@@ -366,7 +366,7 @@ class Mapper3D {
}
private computeBoundingBox(rects: Rect3D[], labels: Label3D[]): Box3D {
if (rects.length == 0) {
if (rects.length === 0) {
return {
width: 1,
height: 1,
@@ -424,10 +424,10 @@ class Mapper3D {
const depth = maxZ - minZ;
return {
width: width,
height: height,
depth: depth,
center: center,
width,
height,
depth,
center,
diagonal: Math.sqrt(width * width + height * height + depth * depth),
};
}

View File

@@ -222,23 +222,23 @@ export class RectsComponent implements OnInit, OnDestroy {
this.resizeObserver?.disconnect();
}
public onSeparationSliderChange(factor: number) {
onSeparationSliderChange(factor: number) {
this.mapper3d.setZSpacingFactor(factor);
this.drawScene();
}
public onRotationSliderChange(factor: number) {
onRotationSliderChange(factor: number) {
this.mapper3d.setCameraRotationFactor(factor);
this.drawScene();
}
public resetCamera() {
resetCamera() {
this.mapper3d.resetCamera();
this.drawScene();
}
@HostListener('wheel', ['$event'])
public onScroll(event: WheelEvent) {
onScroll(event: WheelEvent) {
if (event.deltaY > 0) {
this.doZoomOut();
} else {
@@ -246,46 +246,46 @@ export class RectsComponent implements OnInit, OnDestroy {
}
}
public onCanvasMouseDown(event: MouseEvent) {
onCanvasMouseDown(event: MouseEvent) {
document.addEventListener('mousemove', this.mouseMoveListener);
document.addEventListener('mouseup', this.mouseUpListener);
}
public onMouseMove(event: MouseEvent) {
onMouseMove(event: MouseEvent) {
const distance = new Distance2D(event.movementX, event.movementY);
this.mapper3d.addPanScreenDistance(distance);
this.drawScene();
}
public onMouseUp(event: MouseEvent) {
onMouseUp(event: MouseEvent) {
document.removeEventListener('mousemove', this.mouseMoveListener);
document.removeEventListener('mouseup', this.mouseUpListener);
}
public onZoomInClick() {
onZoomInClick() {
this.doZoomIn();
}
public onZoomOutClick() {
onZoomOutClick() {
this.doZoomOut();
}
public onShowOnlyVisibleModeChange(enabled: boolean) {
onShowOnlyVisibleModeChange(enabled: boolean) {
this.mapper3d.setShowOnlyVisibleMode(enabled);
this.drawScene();
}
public onShowVirtualModeChange(enabled: boolean) {
onShowVirtualModeChange(enabled: boolean) {
this.mapper3d.setShowVirtualMode(enabled);
this.drawScene();
}
public onDisplayIdChange(id: number) {
onDisplayIdChange(id: number) {
this.mapper3d.setCurrentDisplayId(id);
this.drawScene();
}
public onRectClick(event: MouseEvent) {
onRectClick(event: MouseEvent) {
event.preventDefault();
const canvas = event.target as Element;
@@ -323,7 +323,7 @@ export class RectsComponent implements OnInit, OnDestroy {
private notifyHighlightedItem(id: string) {
const event: CustomEvent = new CustomEvent(ViewerEvents.HighlightedChange, {
bubbles: true,
detail: {id: id},
detail: {id},
});
this.elementRef.nativeElement.dispatchEvent(event);
}

View File

@@ -88,14 +88,14 @@ export class TreeComponent {
// TODO (b/263779536): this array is passed down from viewers/presenters and is used to generate
// an identifier supposed to be unique for each viewer. Let's just use a proper identifier
// instead. Each viewer/presenter could pass down a random magic number, an UUID, ...
@Input() dependencies: Array<TraceType> = [];
@Input() dependencies: TraceType[] = [];
@Input() item?: UiTreeNode;
@Input() store!: PersistentStore;
@Input() isFlattened? = false;
@Input() initialDepth = 0;
@Input() highlightedItems: Array<string> = [];
@Input() pinnedItems?: Array<HierarchyTreeNode> = [];
@Input() highlightedItems: string[] = [];
@Input() pinnedItems?: HierarchyTreeNode[] = [];
@Input() itemsClickable?: boolean;
@Input() useGlobalCollapsedState?: boolean;
@Input() isAlwaysCollapsed?: boolean;
@@ -117,7 +117,7 @@ export class TreeComponent {
readonly levelOffset = 24;
nodeElement: HTMLElement;
public childTrackById(index: number, child: UiTreeNode): string {
childTrackById(index: number, child: UiTreeNode): string {
if (child.stableId !== undefined) {
return child.stableId;
}
@@ -156,7 +156,7 @@ export class TreeComponent {
this.nodeElement?.removeEventListener('mouseleave', this.nodeMouseLeaveEventListener);
}
public onNodeClick(event: MouseEvent) {
onNodeClick(event: MouseEvent) {
event.preventDefault();
if (window.getSelection()?.type === 'range') {
return;
@@ -171,7 +171,7 @@ export class TreeComponent {
}
}
public nodeOffsetStyle() {
nodeOffsetStyle() {
const offset = this.levelOffset * this.initialDepth + 'px';
return {
@@ -186,38 +186,38 @@ export class TreeComponent {
}
}
public isPinned() {
isPinned() {
if (this.item instanceof HierarchyTreeNode) {
return this.pinnedItems?.map((item) => `${item.stableId}`).includes(`${this.item.stableId}`);
}
return false;
}
public propagateNewHighlightedItem(newId: string) {
propagateNewHighlightedItem(newId: string) {
this.highlightedItemChange.emit(newId);
}
public propagateNewPinnedItem(newPinnedItem: UiTreeNode) {
propagateNewPinnedItem(newPinnedItem: UiTreeNode) {
this.pinnedItemChange.emit(newPinnedItem);
}
public propagateNewSelectedTree(newTree: UiTreeNode) {
propagateNewSelectedTree(newTree: UiTreeNode) {
this.selectedTreeChange.emit(newTree);
}
public isClickable() {
isClickable() {
return !this.isLeaf(this.item) || this.itemsClickable;
}
public toggleTree() {
toggleTree() {
this.setCollapseValue(!this.isCollapsed());
}
public expandTree() {
expandTree() {
this.setCollapseValue(true);
}
public isCollapsed() {
isCollapsed() {
if (this.isAlwaysCollapsed || this.isLeaf(this.item)) {
return true;
}
@@ -231,11 +231,11 @@ export class TreeComponent {
return this.localCollapsedState;
}
public children(): UiTreeNode[] {
children(): UiTreeNode[] {
return this.item?.children ?? [];
}
public hasChildren() {
hasChildren() {
if (!this.item) {
return false;
}

View File

@@ -71,6 +71,6 @@ describe('TreeComponent', () => {
hasChildren = jasmine.createSpy().and.returnValue(true);
@ViewChild(TreeComponent)
public treeComponent!: TreeComponent;
treeComponent!: TreeComponent;
}
});

View File

@@ -73,42 +73,42 @@ export class TreeNodeComponent {
this.collapseDiffClass = this.updateCollapseDiffClass();
}
public isPropertiesTreeNode() {
isPropertiesTreeNode() {
return !(this.item instanceof HierarchyTreeNode);
}
public showPinNodeIcon() {
showPinNodeIcon() {
return (
(!this.isPropertiesTreeNode() && !UiTreeUtils.isParentNode(this.item.kind ?? '')) ?? false
);
}
public toggleTree(event: MouseEvent) {
toggleTree(event: MouseEvent) {
if (!this.isAlwaysCollapsed) {
event.stopPropagation();
this.toggleTreeChange.emit();
}
}
public showChevron() {
showChevron() {
return !this.isLeaf && !this.flattened && !this.isInPinnedSection;
}
public showLeafNodeIcon() {
showLeafNodeIcon() {
return !this.showChevron() && !this.isInPinnedSection;
}
public expandTree(event: MouseEvent) {
expandTree(event: MouseEvent) {
event.stopPropagation();
this.expandTreeChange.emit();
}
public pinNode(event: MouseEvent) {
pinNode(event: MouseEvent) {
event.stopPropagation();
this.pinNodeChange.emit(this.item);
}
public updateCollapseDiffClass() {
updateCollapseDiffClass() {
if (this.isCollapsed) {
return '';
}

View File

@@ -62,6 +62,6 @@ describe('TreeNodeComponent', () => {
};
@ViewChild(TreeNodeComponent)
public treeNodeComponent!: TreeNodeComponent;
treeNodeComponent!: TreeNodeComponent;
}
});

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
import {Component, Input} from '@angular/core';
import Chip from 'viewers/common/chip';
import {Chip} from 'viewers/common/chip';
import {HierarchyTreeNode, Terminal, UiTreeNode} from 'viewers/common/ui_tree_utils';
import {treeNodeDataViewStyles} from 'viewers/components/styles/tree_node_data_view.styles';
@@ -36,24 +36,24 @@ import {treeNodeDataViewStyles} from 'viewers/components/styles/tree_node_data_v
export class TreeNodeDataViewComponent {
@Input() item!: UiTreeNode;
public chips() {
chips() {
return this.item instanceof HierarchyTreeNode ? this.item.chips : [];
}
public itemShortName() {
itemShortName() {
return this.item instanceof HierarchyTreeNode && this.item.shortName
? this.item.shortName
: this.item.name;
}
public itemTooltip() {
itemTooltip() {
if (this.item.name instanceof Terminal) {
return '';
}
return this.item.name ?? '';
}
public showShortName() {
showShortName() {
return (
this.item instanceof HierarchyTreeNode &&
this.item.simplifyNames &&
@@ -62,7 +62,7 @@ export class TreeNodeDataViewComponent {
);
}
public chipClass(chip: Chip) {
chipClass(chip: Chip) {
return [
'tree-view-internal-chip',
'tree-view-chip',

View File

@@ -33,20 +33,20 @@ import {treeNodePropertiesDataViewStyles} from 'viewers/components/styles/tree_n
export class TreeNodePropertiesDataViewComponent {
@Input() item!: PropertiesTreeNode;
public valueClass() {
valueClass() {
if (!this.item.propertyValue) {
return null;
}
if (this.item.propertyValue == 'null') {
if (this.item.propertyValue === 'null') {
return 'null';
}
if (this.item.propertyValue == 'true') {
if (this.item.propertyValue === 'true') {
return 'true';
}
if (this.item.propertyValue == 'false') {
if (this.item.propertyValue === 'false') {
return 'false';
}

View File

@@ -39,7 +39,7 @@ class ViewerFactory {
ViewerScreenRecording,
];
public createViewers(activeTraceTypes: Set<TraceType>, storage: Storage): Viewer[] {
createViewers(activeTraceTypes: Set<TraceType>, storage: Storage): Viewer[] {
const viewers: Viewer[] = [];
for (const Viewer of ViewerFactory.VIEWERS) {

View File

@@ -33,7 +33,7 @@ class ViewerInputMethodClients extends ViewerInputMethod {
return new PresenterInputMethodClients(this.imeUiCallback, this.getDependencies(), storage);
}
public static readonly DEPENDENCIES: TraceType[] = [TraceType.INPUT_METHOD_CLIENTS];
static readonly DEPENDENCIES: TraceType[] = [TraceType.INPUT_METHOD_CLIENTS];
}
export {ViewerInputMethodClients};

View File

@@ -42,7 +42,7 @@ class ViewerInputMethodManagerService extends ViewerInputMethod {
);
}
public static readonly DEPENDENCIES: TraceType[] = [TraceType.INPUT_METHOD_MANAGER_SERVICE];
static readonly DEPENDENCIES: TraceType[] = [TraceType.INPUT_METHOD_MANAGER_SERVICE];
}
export {ViewerInputMethodManagerService};

View File

@@ -33,7 +33,7 @@ class ViewerInputMethodService extends ViewerInputMethod {
return new PresenterInputMethodService(this.imeUiCallback, this.getDependencies(), storage);
}
public static readonly DEPENDENCIES: TraceType[] = [TraceType.INPUT_METHOD_SERVICE];
static readonly DEPENDENCIES: TraceType[] = [TraceType.INPUT_METHOD_SERVICE];
}
export {ViewerInputMethodService};

View File

@@ -14,10 +14,10 @@
* limitations under the License.
*/
class Events {
public static LogLevelsFilterChanged = 'ViewerProtoLogEvent_LogLevelsFilterChanged';
public static TagsFilterChanged = 'ViewerProtoLogEvent_TagsFilterChanged';
public static SourceFilesFilterChanged = 'ViewerProtoLogEvent_SourceFilesFilterChanged';
public static SearchStringFilterChanged = 'ViewerProtoLogEvent_SearchStringFilterChanged';
static LogLevelsFilterChanged = 'ViewerProtoLogEvent_LogLevelsFilterChanged';
static TagsFilterChanged = 'ViewerProtoLogEvent_TagsFilterChanged';
static SourceFilesFilterChanged = 'ViewerProtoLogEvent_SourceFilesFilterChanged';
static SearchStringFilterChanged = 'ViewerProtoLogEvent_SearchStringFilterChanged';
}
export {Events};

View File

@@ -27,7 +27,7 @@ export class Presenter {
}
//TODO: replace input with something like iterator/cursor (same for other viewers/presenters)
public notifyCurrentTraceEntries(entries: Map<TraceType, any>): void {
notifyCurrentTraceEntries(entries: Map<TraceType, any>): void {
this.entry = entries.get(TraceType.PROTO_LOG) ? entries.get(TraceType.PROTO_LOG)[0] : undefined;
if (this.uiData === UiData.EMPTY) {
this.computeUiDataMessages();
@@ -36,28 +36,28 @@ export class Presenter {
this.notifyUiDataCallback(this.uiData);
}
public onLogLevelsFilterChanged(levels: string[]) {
onLogLevelsFilterChanged(levels: string[]) {
this.levels = levels;
this.computeUiDataMessages();
this.computeUiDataCurrentMessageIndex();
this.notifyUiDataCallback(this.uiData);
}
public onTagsFilterChanged(tags: string[]) {
onTagsFilterChanged(tags: string[]) {
this.tags = tags;
this.computeUiDataMessages();
this.computeUiDataCurrentMessageIndex();
this.notifyUiDataCallback(this.uiData);
}
public onSourceFilesFilterChanged(files: string[]) {
onSourceFilesFilterChanged(files: string[]) {
this.files = files;
this.computeUiDataMessages();
this.computeUiDataCurrentMessageIndex();
this.notifyUiDataCallback(this.uiData);
}
public onSearchStringFilterChanged(searchString: string) {
onSearchStringFilterChanged(searchString: string) {
this.searchString = searchString;
this.computeUiDataMessages();
this.computeUiDataCurrentMessageIndex();
@@ -82,7 +82,7 @@ export class Presenter {
(message: LogMessage) => message.at
);
let filteredMessagesAndOriginalIndex: [number, LogMessage][] = [
let filteredMessagesAndOriginalIndex: Array<[number, LogMessage]> = [
...this.entry!.messages.entries(),
];

Some files were not shown because too many files have changed in this diff Show More