Skip to content

Commit 75f4146

Browse files
committed
add default api key
1 parent e95edb8 commit 75f4146

File tree

10 files changed

+331
-116
lines changed

10 files changed

+331
-116
lines changed

compose/dev/compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ services:
6060
- 3000:3000
6161
environment:
6262
REACT_APP_GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
63+
REACT_APP_CODEIUM_API_KEY: ${CODEIUM_API_KEY}
64+
6365
volumes:
6466
- ../../ui:/app
6567
- ui-node-modules:/app/node_modules

ui/package.json

100644100755
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
"zustand": "^4.1.3"
7171
},
7272
"scripts": {
73-
"generate": "rm -rf ./src/proto && npx buf generate --output ./src/",
73+
"generate": "chmod -R 777 /root && rm -rf ./src/proto && npx buf generate --output ./src/",
7474
"dev": "react-app-rewired start",
7575
"build": "react-app-rewired build --max_old_space_size=4096",
7676
"test": "react-app-rewired test",

ui/src/components/CanvasContextMenu.tsx

100644100755
Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,8 @@ const ItemStyle = {
3737
export function CanvasContextMenu(props) {
3838
const store = useContext(RepoContext);
3939
if (!store) throw new Error("Missing BearContext.Provider in the tree");
40-
const showLineNumbers = useStore(store, (state) => state.showLineNumbers);
41-
const flipShowLineNumbers = useStore(
42-
store,
43-
(state) => state.flipShowLineNumbers
44-
);
4540
const client = useApolloClient();
4641
const autoCompletion = useStore(store, (state) => state.autoCompletion);
47-
const flipAutoCompletion = useStore(
48-
store,
49-
(state) => state.flipAutoCompletion
50-
);
5142

5243
console.log("autoCompletion", autoCompletion);
5344
const isGuest = useStore(store, (state) => state.role === "GUEST");
@@ -78,15 +69,6 @@ export function CanvasContextMenu(props) {
7869
<ListItemText>New Scope</ListItemText>
7970
</MenuItem>
8071
)}
81-
<MenuItem onClick={() => flipAutoCompletion(client)} sx={ItemStyle}>
82-
<ListItemIcon sx={{ color: "inherit" }}>
83-
<AutoFixHighIcon />
84-
</ListItemIcon>
85-
<ListItemText>
86-
{autoCompletion ? "Disable " : "Enable "} Auto Completion (Provided
87-
by Codeium)
88-
</ListItemText>
89-
</MenuItem>
9072
</MenuList>
9173
</Box>
9274
);

ui/src/components/SettingDialog.tsx

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import React, { useEffect, useContext, useState, useRef } from "react";
2+
import DialogTitle from "@mui/material/DialogTitle";
3+
import Dialog from "@mui/material/Dialog";
4+
import DialogActions from "@mui/material/DialogActions";
5+
import DialogContent from "@mui/material/DialogContent";
6+
import DialogContentText from "@mui/material/DialogContentText";
7+
import FormGroup from "@mui/material/FormGroup";
8+
import FormControlLabel from "@mui/material/FormControlLabel";
9+
import TextField from "@mui/material/TextField";
10+
import Switch from "@mui/material/Switch";
11+
import InputAdornment from "@mui/material/InputAdornment";
12+
import Chip from "@mui/material/Chip";
13+
import { useStore } from "zustand";
14+
import { RepoContext } from "../lib/store";
15+
import { Link, Stack } from "@mui/material";
16+
import LaunchIcon from "@mui/icons-material/Launch";
17+
import { useApolloClient } from "@apollo/client";
18+
import Button from "@mui/material/Button";
19+
import DoneIcon from "@mui/icons-material/Done";
20+
import CloseIcon from "@mui/icons-material/Close";
21+
import Snackbar from "@mui/material/Snackbar";
22+
import Alert, { AlertColor } from "@mui/material/Alert";
23+
import { openTokenPage, registerUser } from "../lib/monacoCompletionProvider";
24+
25+
interface SettingDiagProps {
26+
open: boolean;
27+
}
28+
29+
export function SettingDialog({ open = false }: SettingDiagProps) {
30+
const store = useContext(RepoContext);
31+
if (!store) throw new Error("Missing BearContext.Provider in the tree");
32+
const setSettingOpen = useStore(store, (state) => state.setSettingOpen);
33+
const apiKey = useStore(store, (state) => state.user.codeiumAPIKey);
34+
const user = useStore(store, (state) => state.user);
35+
const isCustomToken = useStore(store, (state) => state.isCustomToken);
36+
const setIsCustomToken = useStore(store, (state) => state.setIsCustomToken);
37+
const updateAPIKey = useStore(store, (state) => state.updateAPIKey);
38+
const client = useApolloClient();
39+
const inputRef = useRef<HTMLInputElement>(null);
40+
const [infoShow, setInfoShow] = useState(false);
41+
const [status, setStatus] = useState<"success" | "error" | "warning">(
42+
"success"
43+
);
44+
const [message, setMessage] = useState("");
45+
46+
const onAlertClose = (
47+
event: React.SyntheticEvent | Event,
48+
reason?: string
49+
) => {
50+
if (reason === "clickaway") {
51+
return;
52+
}
53+
setInfoShow(false);
54+
};
55+
56+
const updateToken = async () => {
57+
const token = inputRef.current?.value.trim();
58+
if (!token) {
59+
setStatus("error");
60+
setMessage("Token cannot be empty");
61+
setInfoShow(true);
62+
return;
63+
}
64+
try {
65+
const { api_key, name } = await registerUser(token);
66+
if (api_key === "" || api_key === undefined) {
67+
throw new Error("Invalid token");
68+
}
69+
if (await updateAPIKey(client, api_key)) {
70+
setStatus("success");
71+
setMessage(`${name}, welcome. Token updated`);
72+
setInfoShow(true);
73+
} else {
74+
throw new Error("Update failed");
75+
}
76+
} catch (e) {
77+
setStatus("error");
78+
setMessage((e as Error).message || "Unknown error");
79+
console.log(
80+
(e as Error).message === undefined,
81+
(e as Error).message === ""
82+
);
83+
setInfoShow(true);
84+
return;
85+
}
86+
};
87+
88+
return (
89+
<Dialog open={open}>
90+
<DialogTitle>Auto Completion</DialogTitle>
91+
<DialogContent>
92+
<DialogContentText>
93+
The AI code auto completion is powered by{" "}
94+
<Link href="https://codeium.com/" target="_blank" rel="noreferrer">
95+
Codeium <LaunchIcon fontSize="small" />
96+
</Link>{" "}
97+
You can also use your own token instead of our default API keys, which
98+
records your own activities of using Codeium.
99+
</DialogContentText>
100+
101+
<Stack
102+
direction="row"
103+
flexWrap="wrap"
104+
spacing={{ xs: 1, sm: 2 }}
105+
sx={{ justifyContent: "space-between" }}
106+
>
107+
{apiKey ? (
108+
<Chip
109+
label="Token Verified"
110+
color="success"
111+
size="small"
112+
variant="outlined"
113+
icon={<DoneIcon />}
114+
/>
115+
) : (
116+
<Chip
117+
label="No Stored Token"
118+
color="error"
119+
size="small"
120+
variant="outlined"
121+
icon={<CloseIcon />}
122+
/>
123+
)}
124+
<Button endIcon={<LaunchIcon />} onClick={() => openTokenPage()}>
125+
Get Token
126+
</Button>
127+
</Stack>
128+
129+
<FormGroup>
130+
<FormControlLabel
131+
sx={{ marginRight: 0 }}
132+
control={
133+
<Switch
134+
checked={isCustomToken}
135+
onChange={(e) => setIsCustomToken(e.target.checked)}
136+
/>
137+
}
138+
label="Use my own token"
139+
/>
140+
141+
{isCustomToken && (
142+
<TextField
143+
fullWidth
144+
label="Token"
145+
variant="standard"
146+
inputRef={inputRef}
147+
placeholder="Paste your token here"
148+
InputProps={{
149+
endAdornment: (
150+
<InputAdornment position="end">
151+
<Button onClick={() => updateToken()}>Update</Button>
152+
</InputAdornment>
153+
),
154+
}}
155+
/>
156+
)}
157+
</FormGroup>
158+
<Snackbar
159+
open={infoShow}
160+
autoHideDuration={3000}
161+
anchorOrigin={{ vertical: "top", horizontal: "center" }}
162+
onClose={onAlertClose}
163+
>
164+
<Alert severity={status as AlertColor} onClose={onAlertClose}>
165+
{message}
166+
</Alert>
167+
</Snackbar>
168+
</DialogContent>
169+
<DialogActions>
170+
<Button onClick={() => setSettingOpen(false)}>Close</Button>
171+
</DialogActions>
172+
</Dialog>
173+
);
174+
}

ui/src/components/Sidebar.tsx

100644100755
Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
1313
import Grid from "@mui/material/Grid";
1414
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
1515
import RestartAltIcon from "@mui/icons-material/RestartAlt";
16+
import HelpOutlineOutlinedIcon from "@mui/icons-material/HelpOutlineOutlined";
1617
import Typography from "@mui/material/Typography";
1718
import { useSnackbar, VariantType } from "notistack";
1819

@@ -27,8 +28,12 @@ import { RepoContext } from "../lib/store";
2728
import useMe from "../lib/me";
2829
import { FormControlLabel, FormGroup, Stack, Switch } from "@mui/material";
2930
import { getUpTime } from "../lib/utils";
31+
import { registerCompletion } from "../lib/monacoCompletionProvider";
32+
import { SettingDialog } from "./SettingDialog";
3033
import { toSvg } from "html-to-image";
3134

35+
const defaultAPIKey = process.env.REACT_APP_CODEIUM_API_KEY;
36+
3237
function Flex(props) {
3338
return (
3439
<Box sx={{ display: "flex" }} {...props}>
@@ -54,17 +59,34 @@ function SidebarSettings() {
5459
store,
5560
(state) => state.setShowLineNumbers
5661
);
62+
const isGuest = useStore(store, (state) => state.role === "GUEST");
5763
const autoRunLayout = useStore(store, (state) => state.autoRunLayout);
5864
const setAutoRunLayout = useStore(store, (state) => state.setAutoRunLayout);
5965
const contextualZoom = useStore(store, (state) => state.contextualZoom);
6066
const setContextualZoom = useStore(store, (state) => state.setContextualZoom);
61-
const autoCompletion = useStore(store, (state) => state.autoCompletion);
62-
const flipAutoCompletion = useStore(
67+
const autoCompletion = useStore(
6368
store,
64-
(state) => state.flipAutoCompletion
69+
(state) => !isGuest && state.autoCompletion
6570
);
66-
const client = useApolloClient();
71+
72+
const setAutoCompletion = useStore(store, (state) => state.setAutoCompletion);
6773
const autoLayoutROOT = useStore(store, (state) => state.autoLayoutROOT);
74+
const apiKey = useStore(store, (state) =>
75+
state.isCustomToken
76+
? state.user.codeiumAPIKey ?? defaultAPIKey
77+
: defaultAPIKey
78+
);
79+
const setSettingOpen = useStore(store, (state) => state.setSettingOpen);
80+
81+
useEffect(() => {
82+
console.log("apiKey", apiKey);
83+
if (autoCompletion) {
84+
const dispose = registerCompletion(apiKey);
85+
if (dispose !== null) {
86+
return dispose;
87+
}
88+
}
89+
}, [autoCompletion, apiKey]);
6890
return (
6991
<Box>
7092
<Box>
@@ -162,7 +184,7 @@ function SidebarSettings() {
162184
/>
163185
</FormGroup>
164186
</Tooltip>
165-
<Tooltip title={"Enable Auto Completion"} disableInteractive>
187+
<Tooltip title={"Auto Completion"} disableInteractive>
166188
<FormGroup>
167189
<FormControlLabel
168190
control={
@@ -171,11 +193,32 @@ function SidebarSettings() {
171193
size="small"
172194
color="warning"
173195
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
174-
flipAutoCompletion(client);
196+
setAutoCompletion(event.target.checked);
175197
}}
176198
/>
177199
}
178-
label="Auto Completion"
200+
label={
201+
<>
202+
Auto Completion
203+
<Tooltip
204+
title={"Help"}
205+
disableInteractive
206+
sx={{ display: "inline" }}
207+
>
208+
<IconButton
209+
size="small"
210+
sx={{ display: "inline" }}
211+
onClick={() => setSettingOpen(true)}
212+
disabled={isGuest}
213+
>
214+
<HelpOutlineOutlinedIcon
215+
sx={{ fontSize: 14 }}
216+
></HelpOutlineOutlinedIcon>
217+
</IconButton>
218+
</Tooltip>
219+
</>
220+
}
221+
disabled={isGuest}
179222
/>
180223
</FormGroup>
181224
</Tooltip>
@@ -625,6 +668,7 @@ export const Sidebar: React.FC<SidebarProps> = ({
625668
const store = useContext(RepoContext);
626669
if (!store) throw new Error("Missing BearContext.Provider in the tree");
627670
const isGuest = useStore(store, (state) => state.role === "GUEST");
671+
const settingOpen = useStore(store, (state) => state.settingOpen);
628672
return (
629673
<>
630674
<MyKBar />
@@ -697,6 +741,8 @@ export const Sidebar: React.FC<SidebarProps> = ({
697741
</Stack>
698742
</Box>
699743
</Drawer>
744+
745+
{settingOpen && <SettingDialog open={settingOpen} />}
700746
</>
701747
);
702748
};

ui/src/lib/fetch.tsx

100644100755
File mode changed.

0 commit comments

Comments
 (0)