vzcode 1.19.0 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,17 +8,66 @@ import React, {
8
8
  import { Button, Modal, Form } from './bootstrap';
9
9
  import { ThemeLabel, themes } from './themes';
10
10
  import { VZCodeContext } from './VZCodeContext';
11
- import { fonts } from './Fonts/fonts';
12
- import { toggleRainbowBrackets } from './CodeEditor/rainbowBrackets';
13
11
 
14
- const fontSizes = ['10px','12px','14px','16px', '18px', '20px', '24px'];
12
+ // Font size options for the editor
13
+ const fontSizes = [
14
+ '10px',
15
+ '12px',
16
+ '14px',
17
+ '16px',
18
+ '18px',
19
+ '20px',
20
+ '24px',
21
+ ];
22
+
23
+ // List of system fonts to be detected for availability
24
+ const systemFonts = [
25
+ '-apple-system',
26
+ 'BlinkMacSystemFont',
27
+ 'Segoe UI',
28
+ 'Roboto',
29
+ 'Helvetica Neue',
30
+ 'Arial',
31
+ 'sans-serif',
32
+ 'Courier New',
33
+ 'Georgia',
34
+ 'Tahoma',
35
+ 'Verdana',
36
+ 'Times New Roman',
37
+ 'Trebuchet MS',
38
+ 'Comic Sans MS',
39
+ ];
40
+
41
+ // Utility function to detect if a given font is available
42
+ const isFontAvailable = (font: string): boolean => {
43
+ const testString = 'abcdefghijklmnopqrstuvwxyz0123456789';
44
+ const testSize = '72px';
45
+
46
+ const span = document.createElement('span');
47
+ span.style.fontSize = testSize;
48
+ span.style.visibility = 'hidden';
49
+ span.style.position = 'absolute';
50
+ span.innerHTML = testString;
51
+ document.body.appendChild(span);
52
+
53
+ const defaultFont = 'monospace';
54
+ span.style.fontFamily = defaultFont;
55
+ const defaultWidth = span.offsetWidth;
56
+
57
+ span.style.fontFamily = `${font}, ${defaultFont}`;
58
+ const newWidth = span.offsetWidth;
59
+
60
+ document.body.removeChild(span);
61
+
62
+ return newWidth !== defaultWidth;
63
+ };
15
64
 
16
65
  export const VZSettings = ({
17
66
  enableUsernameField = true,
18
67
  }: {
19
- // Feature flag to enable/disable username field
20
68
  enableUsernameField?: boolean;
21
69
  }) => {
70
+ // Extracting context values for managing settings state
22
71
  const {
23
72
  isSettingsOpen,
24
73
  closeSettings,
@@ -28,58 +77,24 @@ export const VZSettings = ({
28
77
  setUsername,
29
78
  } = useContext(VZCodeContext);
30
79
 
31
- const handleThemeChange = useCallback(
32
- (event: React.ChangeEvent<HTMLSelectElement>) => {
33
- const selectedTheme = event.target.value as ThemeLabel;
34
- setTheme(selectedTheme);
35
- localStorage.setItem('vzcodeSelectedTheme', selectedTheme);
36
- },
37
- [],
38
- );
39
-
40
- useEffect(() => {
41
- const savedTheme = localStorage.getItem('vzcodeSelectedTheme') as ThemeLabel | null;
42
- if (savedTheme) {
43
- setTheme(savedTheme);
44
- } else {
45
- setTheme('vizhub');
46
- }
47
- }, [setTheme]);
48
- // Initialize font and size from localStorage or defaults
49
- // const [selectedFont, setSelectedFont] = useState(
50
- // localStorage.getItem('vzcodeSelectedFont') ||
51
- // 'Roboto Mono',
52
- // );
53
- // const [selectedFontSize, setSelectedFontSize] = useState(
54
- // localStorage.getItem('vzcodeSelectedFontSize') ||
55
- // '16px',
56
- // );
80
+ // State variables for managing font and font size
57
81
  const [selectedFont, setSelectedFont] =
58
82
  useState('Roboto Mono');
59
83
  const [selectedFontSize, setSelectedFontSize] =
60
84
  useState('16px');
85
+ const [availableFonts, setAvailableFonts] = useState<
86
+ string[]
87
+ >([]);
61
88
 
62
- // Initialize rainbowBrackets setting from localStorage or default to 'on'
63
- const [rainbowBrackets, setRainbowBrackets] =
64
- useState('on');
65
-
89
+ // Load saved settings from local storage on initial render
66
90
  useEffect(() => {
67
- // If we're in the browser,
68
91
  if (typeof window !== 'undefined') {
69
- const selectedFontFromLocalStorage: string | null =
92
+ const selectedFontFromLocalStorage =
70
93
  window.localStorage.getItem('vzcodeSelectedFont');
71
-
72
- const selectedFontSizeFromLocalStorage:
73
- | string
74
- | null = window.localStorage.getItem(
75
- 'vzcodeSelectedFontSize',
76
- );
77
-
78
- const rainbowBracketsFromLocalStorage:
79
- | string
80
- | null = window.localStorage.getItem(
81
- 'vzcodeRainbowBrackets',
82
- );
94
+ const selectedFontSizeFromLocalStorage =
95
+ window.localStorage.getItem(
96
+ 'vzcodeSelectedFontSize',
97
+ );
83
98
 
84
99
  if (selectedFontFromLocalStorage !== null) {
85
100
  setSelectedFont(selectedFontFromLocalStorage);
@@ -89,48 +104,42 @@ export const VZSettings = ({
89
104
  selectedFontSizeFromLocalStorage,
90
105
  );
91
106
  }
92
- if (rainbowBracketsFromLocalStorage !== null) {
93
- setRainbowBrackets(rainbowBracketsFromLocalStorage);
94
- }
95
- } else {
96
- // If we're not in the browser, use the default initial width.
97
107
  }
98
108
  }, []);
99
109
 
100
- // Called when the user selects a different font
101
- const handleFontChange = useCallback(
102
- (event: React.ChangeEvent<HTMLSelectElement>) => {
103
- const newFont = event.target.value;
104
- localStorage.setItem('vzcodeSelectedFont', newFont);
105
- setSelectedFont(newFont);
106
- },
107
- [],
108
- );
110
+ // Detect available system fonts and update the state
111
+ useEffect(() => {
112
+ const detectFonts = () => {
113
+ const detectedFonts: string[] = [];
114
+ for (const font of systemFonts) {
115
+ if (isFontAvailable(font)) {
116
+ detectedFonts.push(font);
117
+ if (process.env.NODE_ENV === 'development') {
118
+ console.log(`${font} is available`);
119
+ }
120
+ } else if (process.env.NODE_ENV === 'development') {
121
+ console.log(`${font} is not available`);
122
+ }
123
+ }
124
+ setAvailableFonts(detectedFonts);
125
+ };
109
126
 
110
- // Called when the user selects a different font size
111
- const handleFontSizeChange = useCallback(
112
- (event: React.ChangeEvent<HTMLSelectElement>) => {
113
- const newSize = event.target.value;
114
- localStorage.setItem(
115
- 'vzcodeSelectedFontSize',
116
- newSize,
117
- );
118
- setSelectedFontSize(newSize);
119
- },
120
- [],
121
- );
127
+ detectFonts();
128
+ }, []);
122
129
 
123
- // Called when the user changes the Rainbow Brackets setting
124
- const handleRainbowBracketsChange = useCallback(
125
- (event: React.ChangeEvent<HTMLSelectElement>) => {
126
- const newSetting = event.target.value;
127
- localStorage.setItem('vzcodeRainbowBrackets', newSetting);
128
- setRainbowBrackets(newSetting);
129
- toggleRainbowBrackets(newSetting === 'on');
130
- },
131
- [],
132
- );
130
+ // Reset all settings to default values
131
+ const resetSettings = useCallback(() => {
132
+ setSelectedFont('Roboto Mono');
133
+ setSelectedFontSize('16px');
134
+ setTheme(themes[0].label);
135
+ if (enableUsernameField) {
136
+ setUsername('');
137
+ }
138
+ localStorage.removeItem('vzcodeSelectedFont');
139
+ localStorage.removeItem('vzcodeSelectedFontSize');
140
+ }, [enableUsernameField, setTheme, setUsername]);
133
141
 
142
+ // Update font family in the document's style
134
143
  useEffect(() => {
135
144
  document.body.style.setProperty(
136
145
  '--vzcode-font-family',
@@ -138,6 +147,7 @@ export const VZSettings = ({
138
147
  );
139
148
  }, [selectedFont]);
140
149
 
150
+ // Update font size in the document's style
141
151
  useEffect(() => {
142
152
  document.body.style.setProperty(
143
153
  '--vzcode-font-size',
@@ -147,11 +157,12 @@ export const VZSettings = ({
147
157
 
148
158
  const usernameRef = useRef<HTMLInputElement>(null);
149
159
 
160
+ // Handle username input change
150
161
  const handleUsernameChange = useCallback(() => {
151
162
  setUsername(usernameRef.current?.value || '');
152
163
  }, [setUsername]);
153
164
 
154
- // Function to handle pressing Enter key
165
+ // Close settings modal on Enter key press
155
166
  useEffect(() => {
156
167
  if (isSettingsOpen) {
157
168
  const handleEnterKey = (event: KeyboardEvent) => {
@@ -203,7 +214,9 @@ export const VZSettings = ({
203
214
  <select
204
215
  className="form-select"
205
216
  value={theme}
206
- onChange={handleThemeChange}
217
+ onChange={(e) =>
218
+ setTheme(e.target.value as ThemeLabel)
219
+ }
207
220
  >
208
221
  {themes.map(({ label }) => (
209
222
  <option key={label} value={label}>
@@ -211,37 +224,32 @@ export const VZSettings = ({
211
224
  </option>
212
225
  ))}
213
226
  </select>
214
- <Form.Text className="text-muted">
215
- Select a color theme for the editor
216
- </Form.Text>
217
227
  </Form.Group>
218
228
 
219
229
  <Form.Group className="mb-3" controlId="formFork">
220
230
  <Form.Label>Font</Form.Label>
221
-
222
231
  <select
223
232
  className="form-select"
224
- onChange={handleFontChange}
233
+ onChange={(e) =>
234
+ setSelectedFont(e.target.value)
235
+ }
225
236
  value={selectedFont}
226
237
  >
227
- {fonts.map((font) => (
238
+ {availableFonts.map((font) => (
228
239
  <option key={font} value={font}>
229
240
  {font}
230
241
  </option>
231
242
  ))}
232
243
  </select>
233
-
234
- <Form.Text className="text-muted">
235
- Select font for the editor
236
- </Form.Text>
237
244
  </Form.Group>
238
245
 
239
246
  <Form.Group className="mb-3" controlId="formFork">
240
247
  <Form.Label>Font Size</Form.Label>
241
-
242
248
  <select
243
249
  className="form-select"
244
- onChange={handleFontSizeChange}
250
+ onChange={(e) =>
251
+ setSelectedFontSize(e.target.value)
252
+ }
245
253
  value={selectedFontSize}
246
254
  >
247
255
  {fontSizes.map((size) => (
@@ -250,29 +258,12 @@ export const VZSettings = ({
250
258
  </option>
251
259
  ))}
252
260
  </select>
253
-
254
- <Form.Text className="text-muted">
255
- Select a font size for the editor
256
- </Form.Text>
257
- </Form.Group>
258
-
259
- <Form.Group className="mb-3" controlId="formFork">
260
- <Form.Label>Rainbow Brackets</Form.Label>
261
- <select
262
- className="form-select"
263
- onChange={handleRainbowBracketsChange}
264
- value={rainbowBrackets}
265
- >
266
- <option value="on">On</option>
267
- <option value="off">Off</option>
268
- </select>
269
- <Form.Text className="text-muted">
270
- Toggle Rainbow Brackets
271
- </Form.Text>
272
261
  </Form.Group>
273
-
274
262
  </Modal.Body>
275
263
  <Modal.Footer>
264
+ <Button variant="secondary" onClick={resetSettings}>
265
+ Reset to Default
266
+ </Button>
276
267
  <Button variant="primary" onClick={closeSettings}>
277
268
  Done
278
269
  </Button>
@@ -38,8 +38,8 @@ if (isCopilotEnabled) {
38
38
  openai = new OpenAI(openAIOptions);
39
39
  }
40
40
 
41
- export const handleAICopilot =
42
- (/*TODO shareDBDoc*/) => async (req, res) => {
41
+ export const handleAICopilot = (/*TODO shareDBDoc*/) =>
42
+ async (req, res) => {
43
43
  // Don't break if the AI is not enabled.
44
44
  // This is useful for local development.
45
45
  if (!isCopilotEnabled) {