Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add full-text search #21

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"devDependencies": {
"@types/chrome": "^0.0.128",
"@types/classnames": "^2.2.11",
"@types/flexsearch": "^0.7.2",
"@types/react": "^16.14.2",
"@types/react-dom": "^16.9.10",
"@types/react-fontawesome": "^1.6.4",
Expand Down Expand Up @@ -40,6 +41,7 @@
},
"dependencies": {
"classnames": "^2.2.6",
"flexsearch": "^0.7.21",
"mobx": "^6.1.6",
"mobx-react-lite": "^3.2.0",
"react": "^16.14.0",
Expand Down
48 changes: 43 additions & 5 deletions src/viewer/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ import {
} from "rsocket-core";
import {Encoders} from "rsocket-core/RSocketEncoding";
import Protocol from "devtools-protocol";
import {action, makeObservable, observable} from "mobx";
import {action, makeObservable, observable, computed} from "mobx";
import {observer} from "mobx-react-lite";
import {Index, IndexSearchResult} from "flexsearch";
import WebSocketFrameReceivedEvent = Protocol.Network.WebSocketFrameReceivedEvent;
import WebSocketFrameSentEvent = Protocol.Network.WebSocketFrameSentEvent;
import WebSocketFrame = Protocol.Network.WebSocketFrame;
Expand Down Expand Up @@ -282,6 +283,7 @@ interface WsConnectionState {
id: string,
url?: string,
frames: WsFrameState[];
index: Index;
activeFrame?: number
}

Expand All @@ -293,12 +295,16 @@ export class AppStateStore {
issueWallTime?: number = undefined;
connections = new Map<string, WsConnectionState>();
activeConnection?: string = undefined;
searchValue: string = "";

constructor(handlers: ChromeHandlers) {
makeObservable(this, {
connections: observable,
activeConnection: observable,
selectConnection: action.bound,
search: action.bound,
searchValue: observable,
searchResult: computed,
frameSent: action.bound,
frameReceived: action.bound,
webSocketCreated: action.bound,
Expand All @@ -320,6 +326,8 @@ export class AppStateStore {
return;
}
connection.frames = []
connection.index = new Index({tokenize: "full"})
this.searchValue = ""
}

selectFrame(id?: number) {
Expand All @@ -337,6 +345,24 @@ export class AppStateStore {
this.activeConnection = value;
}

search(value: string) {
this.searchValue = value;
}

get searchResult(): IndexSearchResult {
if (!this.activeConnection) {
return []
}

const connection = this.connections.get(this.activeConnection);
if (!connection) {
return []
}

const result = connection.index.search(this.searchValue);
return result
}

webSocketCreated(event: WebSocketCreatedEvent) {
const {requestId, url} = event;
if (this.connections.get(requestId)) {
Expand All @@ -347,6 +373,7 @@ export class AppStateStore {
id: requestId,
url: url,
frames: [],
index: new Index({tokenize: "full"}),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I deemed a "full" search to be the best fit.

index every possible combination
https://github.com/nextapps-de/flexsearch#tokenizer-prefix-search

activeFrame: undefined,
});
}
Expand Down Expand Up @@ -376,7 +403,9 @@ export class AppStateStore {
frame.binary = stringToBuffer(response.payloadData);
}
const connection = this.ensureConnection(requestId);
const rSocketFrame = tryDeserializeFrame(frame.payload);
connection.frames.push(frame)
connection.index.add(frame.id, (rSocketFrame as any)?.data ?? frame.text ?? frame.payload)
Copy link
Contributor Author

@AndyOGo AndyOGo Jan 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my local tests this works for text frames and rsocket frames data.
Is there any basic thing I missed?

It would be possible to filter for specific frame types or other parts of the protocol, but needs parsing and mapping to human readable names.
https://github.com/rsocket/rsocket/blob/master/Protocol.md

this.activeConnection = requestId;
}
}
Expand All @@ -389,6 +418,7 @@ export class AppStateStore {
const newConnection = {
id: requestId,
frames: [],
index: new Index({tokenize: "full"}),
activeFrame: undefined,
}
this.connections.set(requestId, newConnection);
Expand All @@ -405,7 +435,7 @@ export class AppStateStore {
}

export const App = observer(({store}: { store: AppStateStore }) => {
const {connections, activeConnection} = store;
const {connections, activeConnection, searchValue, searchResult} = store;
if (!activeConnection) {
return <div>No active WebSocket connections</div>
}
Expand All @@ -415,9 +445,10 @@ export const App = observer(({store}: { store: AppStateStore }) => {
}
const {frames, activeFrame} = connection;
const active = frames.find(f => f.id === activeFrame);
const filteredFrames = searchResult.length ? frames.filter((frame) => searchResult.includes(frame.id)) : frames;

const Row = ({ index, style, data }: ListChildComponentProps) => {
const frame = data[index];
const Row = ({ index, style }: ListChildComponentProps) => {
const frame = filteredFrames[index];
Copy link
Contributor Author

@AndyOGo AndyOGo Jan 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SerCeMan
I fixed that regression which I caused in my previous PR
#19 (comment)

If you prefer I may provide a separate PR just for that fix?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries, I'll do another round of testing before releasing the extension.


return (
<FrameEntry
Expand Down Expand Up @@ -450,12 +481,19 @@ export const App = observer(({store}: { store: AppStateStore }) => {
</option>)
}
</select>
<input
type="text"
placeholder="Search frame..."
style={{width: "100%"}}
value={searchValue}
onChange={e => store.search(e.target.value)}
/>
</div>

<div className="frame-list">
<AutoSizer disableWidth>
{({ height }) => (
<FixedSizeList height={height} width="100%" itemCount={frames.length} itemSize={18} innerElementType="ul">
<FixedSizeList height={height} width="100%" itemCount={filteredFrames.length} itemSize={18} innerElementType="ul">
{Row}
</FixedSizeList>
)}
Expand Down
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@
resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.28.tgz#c054e8af4d9dd75db4e63abc76f885168714d4b3"
integrity sha1-wFTor02d11205jq8dviFFocU1LM=

"@types/flexsearch@^0.7.2":
version "0.7.2"
resolved "https://registry.yarnpkg.com/@types/flexsearch/-/flexsearch-0.7.2.tgz#05d982d292e70fcb9fc59347a4a4f98c4ecd9e56"
integrity sha512-Nq0CSpOCyUhaF7tAXSvMtoyBMPGlhNyF+uElhIrrgSiXDmX/bnn9jUX7Us3l81Hzowb9rcgNISke0Nj+3xhd3g==

"@types/glob@^7.1.1":
version "7.1.3"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
Expand Down Expand Up @@ -1832,6 +1837,11 @@ find-up@^4.0.0:
locate-path "^5.0.0"
path-exists "^4.0.0"

flexsearch@^0.7.21:
version "0.7.21"
resolved "https://registry.yarnpkg.com/flexsearch/-/flexsearch-0.7.21.tgz#0f5ede3f2aae67ddc351efbe3b24b69d29e9d48b"
integrity sha512-W7cHV7Hrwjid6lWmy0IhsWDFQboWSng25U3VVywpHOTJnnAZNPScog67G+cVpeX9f7yDD21ih0WDrMMT+JoaYg==

flush-write-stream@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8"
Expand Down