Connection Typeahead/Suggestions (#332)

Adds a list of potential remotes to add and filters it as you type. It
also provides options for reconnecting on a disconnection and
specifically connecting to a local connection
This commit is contained in:
Sylvie Crowe
2024-09-05 17:02:44 -07:00
committed by GitHub
parent 1706131a80
commit fc0b1929ec
11 changed files with 238 additions and 34 deletions
+112 -2
View File
@@ -448,6 +448,10 @@ const ChangeConnectionBlockModal = React.memo(
const changeConnModalOpen = jotai.useAtomValue(changeConnModalAtom);
const [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", blockId));
const isNodeFocused = jotai.useAtomValue(nodeModel.isFocused);
const connection = blockData?.meta?.connection ?? "local";
const connStatusAtom = getConnStatusAtom(connection);
const connStatus = jotai.useAtomValue(connStatusAtom);
const [suggestions, setSuggestions] = React.useState([]);
const changeConnection = React.useCallback(
async (connName: string) => {
if (connName == "") {
@@ -476,6 +480,109 @@ const ChangeConnectionBlockModal = React.memo(
},
[blockId, blockData]
);
React.useEffect(() => {
const loadFromBackend = async () => {
let connList: Array<string>;
try {
connList = await WshServer.ConnListCommand({ timeout: 2000 });
} catch (e) {
console.log("unable to load conn list from backend. using blank list: ", e);
}
let createNew: boolean = true;
if (connSelected == "") {
createNew = false;
}
const filteredList: Array<string> = [];
for (const conn of connList) {
if (conn === connSelected) {
createNew = false;
}
if (conn.includes(connSelected)) {
filteredList.push(conn);
}
}
// priority handles special suggestions when necessary
// for instance, when reconnecting
const newConnectionSuggestion: SuggestionConnectionItem = {
status: "connected",
icon: "arrow-right-arrow-left",
iconColor: "var(--conn-icon-color)",
label: `(+) ${connSelected}`,
value: "",
onSelect: (_: string) => {
changeConnection(connSelected);
globalStore.set(changeConnModalAtom, false);
},
};
const reconnectSuggestion: SuggestionConnectionItem = {
status: "connected",
icon: "arrow-right-arrow-left",
iconColor: "var(--conn-icon-color)",
label: `Reconnect to ${connStatus.connection}`,
value: "",
onSelect: async (_: string) => {
console.log("unimplemented: reconnect");
},
};
const priorityItems: Array<SuggestionConnectionItem> = [];
if (createNew) {
console.log("added to priority items");
priorityItems.push(newConnectionSuggestion);
}
if (connStatus.status == "disconnected" || connStatus.status == "error") {
priorityItems.push(reconnectSuggestion);
}
const prioritySuggestions: SuggestionConnectionScope = {
headerText: "",
items: priorityItems,
};
const localSuggestion: SuggestionConnectionScope = {
headerText: "Local",
items: [
{
status: "connected",
icon: "laptop",
iconColor: "var(--grey-text-color)",
value: "",
label: "Switch to Local Connection",
// TODO: need to specify user name and host name
onSelect: (_: string) => {
changeConnection("");
globalStore.set(changeConnModalAtom, false);
},
},
],
};
const remoteItems = filteredList.map((connName) => {
const item: SuggestionConnectionItem = {
status: "connected",
icon: "arrow-right-arrow-left",
iconColor: "var(--conn-icon-color)",
value: connName,
label: connName,
};
return item;
});
const remoteSuggestions: SuggestionConnectionScope = {
headerText: "Remote",
items: remoteItems,
};
let out: Array<SuggestionsType> = [];
if (prioritySuggestions.items.length > 0) {
out.push(prioritySuggestions);
}
if (localSuggestion.items.length > 0) {
out.push(localSuggestion);
}
if (remoteSuggestions.items.length > 0) {
out.push(remoteSuggestions);
}
setSuggestions(out);
};
loadFromBackend();
}, [connStatus, setSuggestions, connSelected, changeConnection]);
const handleTypeAheadKeyDown = React.useCallback(
(waveEvent: WaveKeyboardEvent): boolean => {
if (keyutil.checkKeyPressed(waveEvent, "Enter")) {
@@ -493,6 +600,9 @@ const ChangeConnectionBlockModal = React.memo(
},
[changeConnModalAtom, viewModel, blockId, connSelected]
);
React.useEffect(() => {
console.log("connSelected is: ", connSelected);
}, [connSelected]);
if (!changeConnModalOpen) {
return null;
}
@@ -500,7 +610,7 @@ const ChangeConnectionBlockModal = React.memo(
<TypeAheadModal
blockRef={blockRef}
anchorRef={connBtnRef}
// suggestions={[]}
suggestions={suggestions}
onSelect={(selected: string) => {
changeConnection(selected);
globalStore.set(changeConnModalAtom, false);
@@ -509,7 +619,7 @@ const ChangeConnectionBlockModal = React.memo(
onKeyDown={(e) => keyutil.keydownWrapper(handleTypeAheadKeyDown)(e)}
onChange={(current: string) => setConnSelected(current)}
value={connSelected}
label="Switch connection"
label="username@host"
onClickBackdrop={() => globalStore.set(changeConnModalAtom, false)}
/>
);
+1 -1
View File
@@ -208,7 +208,7 @@ export const ConnectionButton = React.memo(
const connStatus = jotai.useAtomValue(connStatusAtom);
let showDisconnectedSlash = false;
let connIconElem: React.ReactNode = null;
let color = "#53b4ea";
let color = "var(--conn-icon-color)";
const clickHandler = function () {
setConnModalOpen(true);
};