Improve marking performance

This commit is contained in:
Kuba Orlik 2021-11-21 23:00:55 +01:00
parent 25cd2c2a0c
commit 3eb5dc6f9d
3 changed files with 69 additions and 29 deletions

View File

@ -1,8 +1,13 @@
import React from "react";
import { getMemory } from "../memory";
import { MergedStolenDataEntry, Sources } from "../stolen-data-entry";
import { RequestCluster } from "../request-cluster";
import {
MergedStolenDataEntry,
Sources,
StolenDataEntry,
} from "../stolen-data-entry";
import { hyphenate } from "../util";
import { hyphenate, useEmitter } from "../util";
const MAX_STRING_VALUE_LENGTH = 100;
@ -51,6 +56,7 @@ function StolenDataValue({
entry: MergedStolenDataEntry;
prefixKey?: string;
}) {
const [version] = useEmitter(entry);
const value = entry.getParsedValues(prefixKey)[0];
let body = null;
if (!value) {
@ -64,6 +70,7 @@ function StolenDataValue({
? "2px solid red"
: "2px solid transparent",
}}
data-version={version}
>
{content.slice(0, MAX_STRING_VALUE_LENGTH)}{" "}
{content.length > MAX_STRING_VALUE_LENGTH ? "(...)" : ""}
@ -92,6 +99,38 @@ const icons: Record<Sources, string> = {
header: "H",
};
function StolenDataRow({
entry,
cluster,
}: {
entry: MergedStolenDataEntry;
cluster: RequestCluster;
}) {
const [version] = useEmitter(entry);
return (
<tr
key={origin + cluster.id + entry.getUniqueKey()}
data-key={origin + cluster.id + entry.getUniqueKey()}
data-version={version}
>
<th
style={{
width: "100px",
overflowWrap: "anywhere",
border: entry.hasMark("") ? "2px solid red" : "2px solid transparent",
}}
onClick={() => entry.toggleMark("")}
>
{entry.getNames().map(hyphenate).join(", ")}
</th>
<td>{entry.getSources().map((source) => icons[source])}</td>
<td style={{ wordWrap: "anywhere" as any }}>
<StolenDataValue entry={entry} />
</td>
</tr>
);
}
export default function StolenDataCluster({
origin,
shorthost,
@ -130,27 +169,13 @@ export default function StolenDataCluster({
{cluster
.getStolenData({ minValueLength, cookiesOnly, cookiesOrOriginOnly })
.map((entry) => (
<tr
key={origin + cluster.id + entry.getUniqueKey()}
data-key={origin + cluster.id + entry.getUniqueKey()}
>
<th
style={{
width: "100px",
overflowWrap: "anywhere",
border: entry.hasMark("")
? "2px solid red"
: "2px solid transparent",
}}
onClick={() => entry.toggleMark("")}
>
{entry.getNames().map(hyphenate).join(", ")}
</th>
<td>{entry.getSources().map((source) => icons[source])}</td>
<td style={{ wordWrap: "anywhere" as any }}>
<StolenDataValue entry={entry} />
</td>
</tr>
<StolenDataRow
{...{
entry,
cluster,
key: origin + cluster.id + entry.getUniqueKey(),
}}
/>
))}
</tbody>
</table>

View File

@ -1,7 +1,7 @@
import { TCModel } from "@iabtcf/core";
import { EventEmitter } from "events";
import ExtendedRequest, { HAREntry } from "./extended-request";
import Mark from "./mark";
import { getMemory } from "./memory";
import {
getshorthost,
isJSONObject,
@ -29,7 +29,7 @@ const id = (function* id() {
}
})();
export class StolenDataEntry {
export class StolenDataEntry extends EventEmitter {
public isIAB = false;
public iab: TCModel | null = null;
public id: number;
@ -47,6 +47,7 @@ export class StolenDataEntry {
// // console.log(this.iab);
// this.isIAB = true;
// } catch (e) {}
super();
this.id = id.next().value as number;
this.classification = this.classify();
}
@ -127,7 +128,7 @@ export class StolenDataEntry {
addMark(key: string) {
this.marks.push(new Mark(this, key));
getMemory().emit("change", true); // to trigger rerender
this.emit("change");
}
hasMark(key?: string) {
@ -140,7 +141,7 @@ export class StolenDataEntry {
removeMark(key: string) {
this.marks = this.marks.filter((mark) => mark.key != key);
getMemory().emit("change", true); // to trigger rerender
this.emit("change");
}
toggleMark(key: string) {
@ -194,8 +195,9 @@ export class StolenDataEntry {
}
}
export class MergedStolenDataEntry {
export class MergedStolenDataEntry extends EventEmitter {
constructor(public entries: StolenDataEntry[]) {
super();
const all_marks = unique(
entries.map((entry) => entry.marks).reduce(reduceConcat, [])
);
@ -205,6 +207,20 @@ export class MergedStolenDataEntry {
// getMemory().emit("change"); // to trigger render
}
on(event: string, listener: () => void) {
for (const entry of this.entries) {
entry.on(event, listener);
}
return this;
}
removeListener(event: string, listener: () => void) {
for (const entry of this.entries) {
entry.removeListener(event, listener);
}
return this;
}
hasValue(value: string) {
return this.entries.some((entry) => entry.value === value);
}

View File

@ -1,6 +1,5 @@
import { EventEmitter } from "events";
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import Memory from "./memory";
export type Unpromisify<T> = T extends Promise<infer R> ? R : T;
export type Unarray<T> = T extends Array<infer R> ? R : T;