Skip to content

Add search functionality to Web UI and Connect ssh terminal#48776

Merged
avatus merged 1 commit intomasterfrom
avatus/search
Nov 20, 2024
Merged

Add search functionality to Web UI and Connect ssh terminal#48776
avatus merged 1 commit intomasterfrom
avatus/search

Conversation

@avatus
Copy link
Copy Markdown
Contributor

@avatus avatus commented Nov 12, 2024

This will add the xterm/search-addon addon to our terminals in the web UI ssh sessions as well as Connect. The design of the search UI was inspired by the native browser search in Chrome.

Originally, it was thought that the search addon came with a built-in UI but apparently that isn't the case, so we had to do it ourselves.

Screenshot 2024-11-11 at 6 21 28 PM

Screen.Recording.2024-11-07.at.4.50.01.PM.mov

closes: #38957

changelog: You can now search text within ssh sessions in the Web UI and Teleport Connect

Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
Comment thread web/packages/teleport/src/lib/term/terminal.ts
Comment thread web/packages/teleterm/src/ui/DocumentTerminal/Terminal/ctrl.ts Outdated
Comment on lines +46 to +93
function search(value: string, prev?: boolean) {
if (!xTerm) {
return;
}
const match = theme.colors.terminal.brightYellow;
const activeMatch = theme.colors.terminal.yellow;
setSearchValue(value);

xTerm.search(value, prev, {
decorations: {
matchOverviewRuler: match,
activeMatchColorOverviewRuler: activeMatch,
matchBackground: match,
activeMatchBackground: activeMatch,
},
});
}

const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
search(e.target.value);
};

const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
search(e.currentTarget.value);
}
};

function searchNext() {
search(searchValue);
}

function searchPrevious() {
search(searchValue, true /* search for previous result */);
}

const onEscape = useCallback(() => {
onClose();
xTerm.clearSearch();
xTerm.term.focus();
}, [xTerm, onClose]);

const onSearchResultsChange = useCallback(
(resultIndex: number, resultCount: number) => {
setSearchResults({ resultIndex, resultCount });
},
[]
);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This has a mixture of const x = () => {}, function y() { } and const z = useCallback(() => {}, []) - we should be consistent. My personal preference is useCallback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fair enough. i prefer function y() but i use const when doing useCallback and then a few other cheeky bare const got thrown in there. i'll switch to const and useCallback when needed. thanks

@avatus avatus force-pushed the avatus/search branch 2 times, most recently from 86cd4df to a930d3e Compare November 12, 2024 23:08
@avatus
Copy link
Copy Markdown
Contributor Author

avatus commented Nov 12, 2024

rebased due to conflict. PR feedback handled here and on a930d3e

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Vercel preview here: https://docs-6wic0fycq-goteleport.vercel.app/docs/ver/preview

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Vercel preview here: https://docs-hyszxa56h-goteleport.vercel.app/docs/ver/preview

Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
const isSearchKeyboardEvent = useCallback(
(e: KeyboardEvent) => {
return (
e.type === 'keydown' &&
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We don't have this check in Web. Why is it needed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I just saw other spots in Connect focusing specifically on keydown, didn't think too much on it. I can remove as the method being called on true is idempotent and shouldn't matter on keyup/keydown or duplicates

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As discussed in DMs, let's move this check to the TerminalSearch level.

Comment thread web/packages/teleterm/src/ui/DocumentTerminal/Terminal/ctrl.ts Outdated
@github-actions
Copy link
Copy Markdown
Contributor

🤖 Vercel preview here: https://docs-hh226fzu8-goteleport.vercel.app/docs/ver/preview

return false;
}
// this escape is handled if pressing escape with the term focused
if (e.key === 'Escape') {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not sure if we need the "global" Escape handler, some terminals only close the search when you have the input focused.
But if you want to keep it, we should run it only if the search is shown. Otherwise, we will intercept all Escape key events, even when we don't need them.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I see that you added a check in onKeyDown. However, this place doesn't need to care about it at all, onKeyDown is called only when the input is open.

But we still need to address the issue in registerCustomKeyEventHandler. We don't want to intercept Escape events when the search is closed.
I actually think we should remove closing the search from there. If you take a look at the file transfer, Escape closes it only when it is focused. I think it makes sense to have the same behavior for the search.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah i see. Ok, I've removed it from register and now only check in onKeyDown for the search input. also, I've remove dthe show check on that because onKeyDown can only be called when the input is showing anyway. Let me know if it's good now 👍

Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
const isSearchKeyboardEvent = useCallback(
(e: KeyboardEvent) => {
return (
e.type === 'keydown' &&
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As discussed in DMs, let's move this check to the TerminalSearch level.

Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.test.tsx Outdated
Comment thread docs/pages/connect-your-client/teleport-connect.mdx Outdated
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
@github-actions
Copy link
Copy Markdown
Contributor

🤖 Vercel preview here: https://docs-4jvhqgopl-goteleport.vercel.app/docs/ver/preview

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Vercel preview here: https://docs-pl6lbgnzq-goteleport.vercel.app/docs/ver/preview

Copy link
Copy Markdown
Contributor

@gzdunek gzdunek left a comment

Choose a reason for hiding this comment

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

Left some minor comments, we are almost there!

Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
Comment thread web/packages/teleport/src/lib/term/terminal.ts
Comment thread web/packages/teleterm/src/ui/DocumentTerminal/Terminal/ctrl.ts Outdated
Comment thread web/packages/shared/components/TerminalSearch/index.ts Outdated
return false;
}
// this escape is handled if pressing escape with the term focused
if (e.key === 'Escape') {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I see that you added a check in onKeyDown. However, this place doesn't need to care about it at all, onKeyDown is called only when the input is open.

But we still need to address the issue in registerCustomKeyEventHandler. We don't want to intercept Escape events when the search is closed.
I actually think we should remove closing the search from there. If you take a look at the file transfer, Escape closes it only when it is focused. I think it makes sense to have the same behavior for the search.

Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
Comment thread web/packages/teleterm/src/ui/DocumentTerminal/Terminal/ctrl.ts Outdated
Comment thread web/packages/shared/components/TerminalSearch/TerminalSearch.tsx Outdated
@github-actions
Copy link
Copy Markdown
Contributor

🤖 Vercel preview here: https://docs-6xbf6tt6p-goteleport.vercel.app/docs/ver/preview

Copy link
Copy Markdown
Contributor

@gzdunek gzdunek left a comment

Choose a reason for hiding this comment

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

Left some lasts comments.

🚢

*/

import { render, act, screen } from 'design/utils/testing';
import 'jest-canvas-mock';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think 'jest-canvas-mock' and import '@testing-library/jest-dom' do nothing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

they were used before but i dont think anything is needed with them now.

})),
}));

const createMockXTerm = () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's remove the references to xterm in tests/stories as well, I'd just name it terminalMock.

Comment on lines +124 to +131
}, [
onEscape,
onOpen,
searchInputRef,
terminalSearcher,
show,
isSearchKeyboardEvent,
]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There are some unnecessary deps:

Suggested change
}, [
onEscape,
onOpen,
searchInputRef,
terminalSearcher,
show,
isSearchKeyboardEvent,
]);
}, [isSearchKeyboardEvent, onOpen, terminalSearcher]);

FileTransferRequests,
FileTransferContextProvider,
} from 'shared/components/FileTransfer';
import { TerminalSearch } from 'shared/components/TerminalSearch/TerminalSearch';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
import { TerminalSearch } from 'shared/components/TerminalSearch/TerminalSearch';
import { TerminalSearch } from 'shared/components/TerminalSearch';

FileTransfer,
FileTransferContextProvider,
} from 'shared/components/FileTransfer';
import { TerminalSearch } from 'shared/components/TerminalSearch/TerminalSearch';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
import { TerminalSearch } from 'shared/components/TerminalSearch/TerminalSearch';
import { TerminalSearch } from 'shared/components/TerminalSearch';

Comment thread docs/pages/connect-your-client/teleport-connect.mdx Outdated
openProfiles: 'Ctrl+Shift+I',
terminalCopy: 'Ctrl+Shift+C',
terminalPaste: 'Ctrl+Shift+V',
terminalSearch: 'Ctrl+F',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I just checked the terminal apps on Windows and Linux and they use Ctrl+Shift+F for search. I believe it's because Ctrl+F is used to move the cursor one character forward in bash. Please switch these shortcuts from Ctrl+F in Connect to Ctrl+Shift+F (and remember about updating the docs).

FYI we will have the same problem in Web UI where we overwrite Ctrl+F. We have no choice on Linux and Windows where this is a combination that opens the native search anyway. On macOS in theory we could only intercept Meta+F and leave Ctrl+F for the terminal, but I think we don't have a reliable way to test if the user is on Mac. So I guess we have to leave it as is.

@avatus
Copy link
Copy Markdown
Contributor Author

avatus commented Nov 20, 2024

@ryanclark im about to finish gz's last comments. anything left from you?

@avatus avatus requested a review from ryanclark November 20, 2024 15:28
Copy link
Copy Markdown
Member

@ryanclark ryanclark left a comment

Choose a reason for hiding this comment

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

all good from me

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Vercel preview here: https://docs-g9ear6eqx-goteleport.vercel.app/docs

Merged via the queue into master with commit ad5963a Nov 20, 2024
@avatus avatus deleted the avatus/search branch November 20, 2024 16:10
@public-teleport-github-review-bot
Copy link
Copy Markdown

@avatus See the table below for backport results.

Branch Result
branch/v16 Failed
branch/v17 Create PR

avatus added a commit that referenced this pull request Nov 20, 2024
Backport #48776 to branch/v16

changelog: You can now search text within ssh sessions in the Web UI and
Teleport Connect
avatus added a commit that referenced this pull request Nov 20, 2024
Backport #48776 to branch/v16

changelog: You can now search text within ssh sessions in the Web UI and
Teleport Connect
github-merge-queue Bot pushed a commit that referenced this pull request Nov 20, 2024
…9270)

Backport #48776 to branch/v16

changelog: You can now search text within ssh sessions in the Web UI and
Teleport Connect
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Web UI does not provide the ability to search within an SSH session

3 participants