@dao42/d42paas-front 0.4.8 → 0.4.9

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.
Files changed (69) hide show
  1. package/package.json +2 -3
  2. package/src/_bundle.tsx +0 -283
  3. package/src/app.tsx +0 -356
  4. package/src/assets/code-brackets.svg +0 -1
  5. package/src/assets/colors.svg +0 -1
  6. package/src/assets/comments.svg +0 -1
  7. package/src/assets/direction.svg +0 -1
  8. package/src/assets/flow.svg +0 -1
  9. package/src/assets/plugin.svg +0 -1
  10. package/src/assets/repo.svg +0 -1
  11. package/src/assets/stackalt.svg +0 -1
  12. package/src/components/Avatar/index.tsx +0 -27
  13. package/src/components/CanvasHelper/index.tsx +0 -89
  14. package/src/components/Console/index.tsx +0 -88
  15. package/src/components/Editor/index copy.tsx +0 -1010
  16. package/src/components/Editor/index.tsx +0 -1011
  17. package/src/components/FileTree/index.tsx +0 -478
  18. package/src/components/LiveContent/index.tsx +0 -221
  19. package/src/components/LiveContent/video.tsx +0 -213
  20. package/src/components/LottieAnim/index.tsx +0 -41
  21. package/src/components/Message/index.tsx +0 -64
  22. package/src/components/Model/index.tsx +0 -42
  23. package/src/components/OutputBrowser/index.tsx +0 -180
  24. package/src/components/Skeleton/index.tsx +0 -41
  25. package/src/components/Tabs/index.tsx +0 -23
  26. package/src/components/Terminal/index.tsx +0 -127
  27. package/src/components/ToolBar/index.tsx +0 -169
  28. package/src/components/XTerm/index.tsx +0 -113
  29. package/src/components/index.tsx +0 -4
  30. package/src/components/loading/index.tsx +0 -284
  31. package/src/enum/FExtension.ts +0 -168
  32. package/src/helpers/collections/IoClient.tsx +0 -314
  33. package/src/helpers/collections/errorCatcher.tsx +0 -0
  34. package/src/helpers/collections/idb.tsx +0 -186
  35. package/src/helpers/collections/localStorage.tsx +0 -13
  36. package/src/helpers/collections/mock.tsx +0 -30
  37. package/src/helpers/collections/playgroundInit.tsx +0 -316
  38. package/src/helpers/collections/replay.tsx +0 -168
  39. package/src/helpers/collections/socket.tsx +0 -6
  40. package/src/helpers/collections/toast.tsx +0 -19
  41. package/src/helpers/collections/userTool.tsx +0 -12
  42. package/src/helpers/collections/util.tsx +0 -4
  43. package/src/helpers/index.tsx +0 -6
  44. package/src/helpers/monaco/monaco-ot-adapter.tsx +0 -476
  45. package/src/hooks/collections/useOT.tsx +0 -39
  46. package/src/hooks/index.tsx +0 -1
  47. package/src/index.html +0 -49
  48. package/src/pages/index.tsx +0 -452
  49. package/src/public/dev.html +0 -35
  50. package/src/public/index.html +0 -50
  51. package/src/public/sdkserver.html +0 -36
  52. package/src/stores/index.tsx +0 -1
  53. package/src/stores/oTStore.tsx +0 -310
  54. package/src/stories/BrowserWindow.tsx +0 -30
  55. package/src/stories/Console.tsx +0 -46
  56. package/src/stories/Editor.tsx +0 -37
  57. package/src/stories/FileTree.tsx +0 -50
  58. package/src/stories/Shell.tsx +0 -53
  59. package/src/stories/introduction.stories.mdx +0 -193
  60. package/src/stories/page.tsx +0 -71
  61. package/src/styles/collections/iconfont.scss +0 -1
  62. package/src/styles/collections/tabs-costumers.scss +0 -20
  63. package/src/styles/collections/tailwind.scss +0 -3
  64. package/src/styles/collections/tree-costumers.scss +0 -53
  65. package/src/styles/collections/utility.scss +0 -10
  66. package/src/styles/collections/xterm-costumers.scss +0 -47
  67. package/src/styles/index.css +0 -21
  68. package/src/types/editor.d.ts +0 -31
  69. package/src/types/index.d.ts +0 -166
@@ -1,1010 +0,0 @@
1
- import React, { useRef, useEffect, useState } from 'react';
2
- import * as monacoCore from 'monaco-editor-core';
3
- import * as monaco from 'monaco-editor';
4
- import { oTStore } from '~/stores';
5
- import { SerializedTextOperation, TextOperation } from 'ot';
6
- import * as ot from 'ot';
7
- import create from 'zustand';
8
- import { IoClient, IsMe } from '~/helpers';
9
- import { useOT } from '~/hooks';
10
- import { setLocalFile } from '~/helpers/collections/idb';
11
- import { FExtension } from '~/enum/FExtension';
12
- import { T_UserInfo, userListStore, userStore } from '~/stores/oTStore';
13
- import styled from '@emotion/styled';
14
- import { pick, throttle } from 'lodash';
15
- import normalizeUrl from 'normalize-url';
16
- import { listen } from '@codingame/monaco-jsonrpc';
17
- import ReconnectingWebSocket from 'reconnecting-websocket';
18
-
19
- import {
20
- MonacoLanguageClient,
21
- MessageConnection,
22
- CloseAction,
23
- ErrorAction,
24
- MonacoServices,
25
- createConnection,
26
- } from '@codingame/monaco-languageclient';
27
- import { Toast } from '~/helpers/collections/toast';
28
-
29
- // import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker';
30
- // import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker';
31
- // import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker';
32
- // import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker';
33
- // import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker';
34
-
35
- // self.MonacoEnvironment = {
36
- // getWorker(_, label) {
37
- // if (label === 'json') {
38
- // return new jsonWorker();
39
- // }
40
- // if (label === 'css' || label === 'scss' || label === 'less') {
41
- // return new cssWorker();
42
- // }
43
- // if (label === 'html' || label === 'handlebars' || label === 'razor') {
44
- // return new htmlWorker();
45
- // }
46
- // if (label === 'typescript' || label === 'javascript') {
47
- // return new tsWorker();
48
- // }
49
- // return new editorWorker();
50
- // },
51
- // };
52
-
53
- const APP_DIR = '/home/runner/app';
54
-
55
- // eslint-disable-next-line no-var
56
- var INIT_LANGUAGE = 'ruby';
57
- let to_save_operation;
58
- // const OPERATION_SWICHER: boolean = false;
59
- const docServer = new Map();
60
-
61
- const useValue = create<{
62
- delta: any;
63
- usersDelta: any[];
64
- selectionOp: unknown;
65
- selectionAcks: any[];
66
- setSelectionAck: (val: any) => void;
67
- clearSelectionAcks: () => void;
68
- setDelta: (val: any) => void;
69
- setUsersDelta: (val: any[]) => void;
70
- position: monaco.Position;
71
- setPosition: (arg: monaco.Position) => void;
72
- value: string;
73
- setValue: (val: string) => void;
74
- versionId: number;
75
- setVersionId: (arg?: number) => void;
76
- setSelectionOp: (arg?: unknown) => void;
77
- }>((set) => ({
78
- delta: '',
79
- selectionOp: null,
80
- usersDelta: [],
81
- versionId: 0,
82
- position: ([] as unknown) as monaco.Position,
83
- selectionAcks: [],
84
- setSelectionAck: (arg) =>
85
- set((state) => ({
86
- selectionAcks: [...state.selectionAcks, arg],
87
- })),
88
- clearSelectionAcks: () =>
89
- set(() => ({
90
- selectionAcks: [],
91
- })),
92
- setVersionId: (arg) =>
93
- set(({ versionId }) => ({
94
- versionId: arg || arg === 0 ? arg : versionId + 1,
95
- })),
96
- setDelta: (arg) => set(() => ({ delta: arg })),
97
- setUsersDelta: (arg) => set(() => ({ usersDelta: arg })),
98
- setPosition: (arg) => set(() => ({ position: arg })),
99
- value: '',
100
- setValue: (arg) => set(() => ({ value: arg })),
101
- setSelectionOp: (arg) => set(() => ({ selectionOp: arg })),
102
- }));
103
-
104
- let editor: monaco.editor.IStandaloneCodeEditor;
105
-
106
- // monaco.editor.defineTheme('myTheme', {
107
- // base: 'vs',
108
- // inherit: true,
109
- // rules: [
110
- // {
111
- // background: '#EDF9FA',
112
- // token: 'dasjoajfa',
113
- // },
114
- // ],
115
- // colors: {
116
- // 'editor.foreground': '#000000',
117
- // 'editor.background': '#EDF9FA',
118
- // 'editorCursor.foreground': '#8B0000',
119
- // 'editor.lineHighlightBackground': '#0000FF20',
120
- // 'editorLineNumber.foreground': '#008800',
121
- // 'editor.selectionBackground': '#88000030',
122
- // 'editor.inactiveSelectionBackground': '#88000015',
123
- // },
124
- // });
125
-
126
- // monaco.editor.setTheme('myTheme');
127
-
128
- // const color = 'red';
129
- // const name = 'HOST';
130
- const EditorLayout = styled.div<{ userList: T_UserInfo[] }>`
131
- .contentWidgets {
132
- visibility: hidden;
133
- }
134
- .monaco-label {
135
- font-size: 12px;
136
- border-radius: 2px;
137
- padding: 2px 10px;
138
- transform: scale(0.8);
139
- visibility: hidden;
140
- }
141
- .label-visible {
142
- visibility: visible !important;
143
- }
144
- ${(props) =>
145
- props.userList.map(
146
- (u) =>
147
- '.' +
148
- u.role +
149
- '{' +
150
- 'background:' +
151
- u.color +
152
- ';' +
153
- 'width: 2px !important;' +
154
- '}',
155
- )}
156
- ${(props) =>
157
- props.userList.map(
158
- (u) =>
159
- '.' +
160
- u.role +
161
- '-selection' +
162
- '{' +
163
- 'background:' +
164
- u.color +
165
- 'a6' +
166
- ';' +
167
- 'color: #fff' +
168
- ';' +
169
- 'width: 2px !important;' +
170
- '}',
171
- )}
172
- `;
173
-
174
- // const throttled = throttle((a) => {
175
- // // console.log(a);
176
- // }, 1000);
177
-
178
- export const Editor: React.FC<{
179
- doc?: string;
180
- docType?: string;
181
- }> = ({ doc, docType }) => {
182
- // debugger;
183
- console.log('hi')
184
- // const io = useOT((state) => state.socket);
185
- const divEl = useRef<HTMLDivElement>(null);
186
- const [docVal, setDocVal] = useState<string>(doc ? doc : '');
187
- const [pos, setPos] = useState<monaco.Position>(null!);
188
- const file = oTStore((state) => state.doc);
189
- const setFromServer = oTStore((state) => state.setFromServer);
190
- const [client, setClient] = useState(new IoClient(0));
191
- const OTSTATE = oTStore((state) => state);
192
- const USERLISTSTORE = userListStore((state) => state);
193
- const setPosition = useValue((state) => state.setPosition);
194
- const setValue = useValue((state) => state.setValue);
195
- const setDelta = useValue((state) => state.setDelta);
196
- // const [languageModal, setLanguageModal] = useState({
197
- // value: docVal,
198
- // // language: 'typescript',
199
- // language: FExtension.py,
200
- // theme: 'vs-dark',
201
- // // theme: 'myTheme',
202
- // automaticLayout: true,
203
- // fixedOverflowWidgets: true,
204
- // // scrollBeyondLastLine: true,
205
- // // roundedSelection: true,
206
- // // showFoldingControls: false,
207
- // // autoIndent: true,
208
- // // cursorStyle: "line",
209
- // // fontWeight: 400,
210
- // // minimap: false
211
- // scrollbar: {
212
- // // Subtle shadows to the left & top. Defaults to true.
213
- // useShadows: true,
214
-
215
- // // Render vertical arrows. Defaults to false.
216
- // verticalHasArrows: true,
217
- // // Render horizontal arrows. Defaults to false.
218
- // horizontalHasArrows: false,
219
-
220
- // // // Render vertical scrollbar.
221
- // // // Accepted values: 'auto', 'visible', 'hidden'.
222
- // // // Defaults to 'auto'
223
- // // vertical: 'hidden',
224
- // // // Render horizontal scrollbar.
225
- // // // Accepted values: 'auto', 'hidden', 'hidden'.
226
- // // // Defaults to 'auto'
227
- // // horizontal: 'hidden',
228
-
229
- // verticalScrollbarSize: 8,
230
- // horizontalScrollbarSize: 8,
231
- // arrowSize: 5,
232
- // },
233
- // });
234
-
235
- const cursorTool = (evt: monaco.editor.ICursorSelectionChangedEvent) => {
236
- // const { CRDTInfo } = oTStore.getState();
237
- const { userInfo } = userStore.getState();
238
-
239
- const selection = [
240
- [
241
- evt.selection.startLineNumber,
242
- evt.selection.startColumn,
243
- evt.selection.endLineNumber,
244
- evt.selection.endColumn,
245
- evt.selection.selectionStartLineNumber,
246
- evt.selection.selectionStartColumn,
247
- evt.selection.positionColumn,
248
- evt.selection.positionLineNumber,
249
- ],
250
- ...evt.secondarySelections.map((s) => [
251
- s.startLineNumber,
252
- s.startColumn,
253
- s.endLineNumber,
254
- s.endColumn,
255
- s.selectionStartLineNumber,
256
- s.selectionStartColumn,
257
- s.positionColumn,
258
- s.positionLineNumber,
259
- ]),
260
- ];
261
- const crdt: D42_FrontType.CRDT = {
262
- timestamp: Date.now().toString(),
263
- selection,
264
- file: {
265
- action: 'Update',
266
- path: oTStore.getState()?.doc.path,
267
- },
268
- userInfo: pick(userInfo, 'uuid', 'role'),
269
- };
270
- // sendPos = selection;
271
- useOT.getState()?.socket.emit('selection', JSON.stringify(crdt));
272
- };
273
-
274
- const receiveOperation = (revision, operation, path) => {
275
- // const sOperation = docServer.get(path).operation;
276
- // if (operation.baseLength === sOperation.baseLength) {
277
- // const { transform } = operation.constructor;
278
- // operation = transform(operation, sOperation)[1];
279
- // }
280
- client.receiveOperation = operation;
281
- return { operation };
282
- };
283
-
284
- const editorEventBinder = () => {
285
- editor.onKeyDown((evt) => {
286
- setFromServer(false);
287
- // if ((evt.ctrlKey || evt.metaKey) && (evt.keyCode === 109 || evt.keyCode === 57)) {
288
- if (evt.keyCode === 49) {
289
- (evt.ctrlKey || evt.metaKey) && evt.preventDefault();
290
- }
291
- });
292
-
293
- editor.onDidChangeCursorSelection((evt) => {
294
- if (oTStore.getState().appStatus === 'replay') return;
295
-
296
- // console.log('当前revision:', client.revision);
297
- if (evt.source === 'api') {
298
- cursorTool(evt);
299
- }
300
- if (evt.reason === 0 || evt.source === 'model') return;
301
- cursorTool(evt);
302
- });
303
-
304
- editor.onDidChangeModelContent((evt) => {
305
- const { appStatus, fromServer, doc } = oTStore.getState();
306
- // 回放状态,不进行文件数据改变
307
- if (appStatus === 'replay') return;
308
- if (fromServer) return;
309
- // const docLength = editor.getModel().getValueLength(); // 文档长度
310
- const editorValue = editor.getValue();
311
- // const { isFlush, changes } = evt;
312
- const { isFlush, changes } = evt;
313
- // const changes = evt.changes.sort(
314
- // (c1, c2) => c1.rangeOffset - c2.rangeOffset,
315
- // );
316
- if (!isFlush) {
317
- setPosition(editor.getPosition());
318
- let keepString = 0;
319
- let rangeLengthamount = 0;
320
- const rangeOffsetthamount = 0;
321
- // let lastRangeOffsetthamount = 0;
322
-
323
- const valuelength =
324
- editorValue.length -
325
- changes.reduce(
326
- (change, nextChange, i) =>
327
- change - nextChange.rangeLength + nextChange.text.length,
328
- 0,
329
- );
330
- const operation = changes
331
- .sort((c1, c2) => c1.rangeOffset - c2.rangeOffset)
332
- .map((change, i) => {
333
- rangeLengthamount += i === 0 ? 0 : change.rangeLength;
334
- keepString += i === 0 ? 0 : change.text.length;
335
-
336
- return new TextOperation()
337
- .retain(
338
- i === 0
339
- ? change.rangeOffset
340
- : change.rangeOffset - rangeLengthamount + keepString,
341
- )
342
- .delete(change.rangeLength)
343
- .insert(change.text)
344
- .retain(
345
- // useValue.getState().value.length -
346
- valuelength - change.rangeOffset - change.rangeLength,
347
- );
348
- })
349
- .reduce((a, b) => a.compose(b));
350
-
351
- // const operation = changes
352
- // .sort((c1, c2) => c1.rangeOffset - c2.rangeOffset)
353
- // .map((change, i) => {
354
- // rangeLengthamount += i === 0 ? 0 : change.rangeLength;
355
- // keepString += i === 0 ? 0 : change.text.length;
356
-
357
- // return new TextOperation()
358
- // .retain(
359
- // i === 0
360
- // ? change.rangeOffset
361
- // : change.rangeOffset - rangeLengthamount + keepString,
362
- // )
363
- // .delete(change.rangeLength)
364
- // .insert(change.text)
365
- // .retain(
366
- // // useValue.getState().value.length -
367
- // valuelength - change.rangeOffset - change.rangeLength,
368
- // );
369
- // });
370
-
371
- /* end */
372
- // console.log('本地revision', client.revision);
373
- // 单文件模式
374
- // setTimeout(() => {
375
- setLocalFile(doc.path ? doc.path : 'singleFile', editor.getValue());
376
- // to_save_operation = operation;
377
- client.applyClient(operation);
378
- // }, 0);
379
- } else {
380
- setValue(changes[0].text);
381
- }
382
- });
383
-
384
- editor.createContextKey('save', true);
385
-
386
- editor.addCommand(
387
- monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS,
388
- () => {
389
- const { doc, setFileSaved } = oTStore.getState();
390
-
391
- useOT.getState().socket.emit('saveFile', doc.path);
392
- // alert('保存成功~');
393
- // Toast.message()
394
-
395
- Toast.message({
396
- type: 'success',
397
- content: '保存成功~~🤘 ↑↑↓↓←→←→ABAB',
398
- placement: 'topCenter',
399
- });
400
- // client.applyClient(to_save_operation);
401
- },
402
- 'save',
403
- );
404
-
405
- client.sendOperation = function (revision, operation) {
406
- if (oTStore.getState().appStatus === 'replay') return;
407
-
408
- const { userInfo } = userStore.getState();
409
- const { doc } = oTStore.getState();
410
- // console.log(file);
411
- const crdt: D42_FrontType.CRDT = {
412
- timestamp: Date.now().toString(),
413
- userInfo: pick(userInfo, ['role', 'uuid']),
414
- editor: {
415
- operation,
416
- revision,
417
- evtType: 'Editor',
418
- },
419
- file: {
420
- action: 'Update',
421
- path: doc.path,
422
- },
423
- };
424
-
425
- useOT.getState().socket.emit('editFile', JSON.stringify(crdt));
426
- };
427
- };
428
-
429
- const updateLspOps = ({ value, path, language, CRDTInfo, doc }) => {
430
- let gotModel = monaco.editor
431
- .getModels()
432
- .find((x) => new RegExp(path).test(x.uri.path));
433
-
434
- if (!gotModel) {
435
- gotModel = monaco.editor.createModel(
436
- value,
437
- language,
438
- monaco.Uri.parse(`file://${APP_DIR}${path}`),
439
- // monaco.Uri.parse(
440
- // 'file:///Users/unamed/git/testForLSP/src/main/java/lsptest/Main.java',
441
- // ),
442
-
443
- // monaco.Uri.parse(`inmemory://${path}`),
444
- // monaco.Uri.parse(`file://${path}`),
445
- // monaco.Uri.parse(`${path}`),
446
- // monaco.Uri.parse(`file:///abs/file.rb`),
447
- // monaco.Uri.parse('inmemory:///abs/path/to/demo/ts/file.rb'),
448
- );
449
- // gotModel = monaco.editor.createModel(
450
- // value,
451
- // language,
452
- // // monaco.Uri.parse(`${path}`),
453
- // monaco.Uri.parse(
454
- // 'file:///Users/unamed/git/testForLSP/src/main/java/Main.java',
455
- // ),
456
-
457
- // // monaco.Uri.parse(`inmemory://${path}`),
458
- // // monaco.Uri.parse(`file://${path}`),
459
- // // monaco.Uri.parse(`${path}`),
460
- // // monaco.Uri.parse(`file:///abs/file.rb`),
461
- // // monaco.Uri.parse('inmemory:///abs/path/to/demo/ts/file.rb'),
462
- // );
463
- // gotModel = monaco.editor.createModel(
464
- // value,
465
- // language,
466
- // // monaco.Uri.parse(`${path}`),
467
- // monaco.Uri.parse(
468
- // 'file:///Users/unamed/git/testForLSP/src/main/java/lsptest/sample.java',
469
- // ),
470
-
471
- // // monaco.Uri.parse(`inmemory://${path}`),
472
- // // monaco.Uri.parse(`file://${path}`),
473
- // // monaco.Uri.parse(`${path}`),
474
- // // monaco.Uri.parse(`file:///abs/file.rb`),
475
- // // monaco.Uri.parse('inmemory:///abs/path/to/demo/ts/file.rb'),
476
- // );
477
- }
478
-
479
- client.revision = CRDTInfo.editor.revision ? CRDTInfo.editor.revision : 0;
480
-
481
- editor.setModel(gotModel);
482
-
483
- docServer.set(file.path, {
484
- operation: [],
485
- revision: client.revision,
486
- value: file.value,
487
- });
488
- setLocalFile(doc.path, file.value);
489
-
490
- // editor.setValue(file.value);
491
- };
492
-
493
- const lspServerInject = (lan, disable?: boolean) => {
494
- // monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
495
- // allowNonTsExtensions: true,
496
- // // allowJs: true,
497
- // target: 99,
498
- // paths: {
499
- // '@/*': ['./'],
500
- // },
501
- // baseUrl: './',
502
- // });
503
- monaco.languages.register({
504
- id: 'ruby',
505
- extensions: ['.rb'],
506
- aliases: ['ruby', 'RUBY'],
507
- // extensions: ['.rb', '.rjs', '.gemspec', '.rbx'],
508
- // aliases: ['Ruby', 'ruby', 'rjs', 'gemspec', 'rb'],
509
- // mimetypes: ['application/json']
510
- });
511
- monaco.languages.register({
512
- id: 'java',
513
- extensions: ['.java'],
514
- aliases: ['java', 'JAVA'],
515
- // extensions: ['.rb', '.rjs', '.gemspec', '.rbx'],
516
- // aliases: ['Ruby', 'ruby', 'rjs', 'gemspec', 'rb'],
517
- // mimetypes: ['application/json']
518
- });
519
- monaco.languages.register({
520
- id: 'typescript',
521
- extensions: ['.ts'],
522
- aliases: ['TypeScript', 'ts', 'TS', 'typescript'],
523
- // mimetypes: ['application/json']
524
- });
525
-
526
- /**
527
- * Uniform Resource Identifier (Uri) http://tools.ietf.org/html/rfc3986.
528
- * This class is a simple parser which creates the basic component parts
529
- * (http://tools.ietf.org/html/rfc3986#section-3) with minimal validation
530
- * and encoding.
531
- *
532
- * ```txt
533
- * foo://example.com:8042/over/there?name=ferret#nose
534
- * \_/ \______________/\_________/ \_________/ \__/
535
- * | | | | |
536
- * scheme authority path query fragment
537
- * | _____________________|__
538
- * / \ / \
539
- * urn:example:animal:ferret:nose
540
- * ```
541
- */
542
- // monaco.editor.createModel(
543
- // 'printF',
544
- // 'typescript',
545
- // monaco.Uri.parse('file:///index.rb'),
546
- // );
547
- // monaco.editor.createModel(
548
- // 'export const callYou = () => { // console.log("hi") }',
549
- // 'typescript',
550
- // monaco.Uri.parse('file:///coding2/c2#/sample.ts'),
551
- // );
552
-
553
- if (disable) return;
554
- MonacoServices.install(monaco as typeof monacoCore);
555
- // console.log(oTStore.getState().dockerInfo);
556
- const { lspUrl, ticket } = oTStore.getState().dockerInfo;
557
- if (!lspUrl) return;
558
- // const webSocket = (new ReconnectingWebSocket('ws://192.168.2.15:7700', [], {
559
- const webSocket = (new ReconnectingWebSocket(
560
- `wss://${lspUrl}/${ticket}`,
561
- [],
562
- {
563
- // const webSocket = (new ReconnectingWebSocket(
564
- // 'ws://192.168.2.9:3001/runner',
565
- // [],
566
- // {
567
- maxReconnectionDelay: 10000,
568
- minReconnectionDelay: 1000,
569
- reconnectionDelayGrowFactor: 1.3,
570
- connectionTimeout: 10000,
571
- maxRetries: Infinity,
572
- debug: false,
573
- },
574
- ) as unknown) as WebSocket;
575
-
576
- // listen when the web socket is opened
577
- listen({
578
- webSocket,
579
- onConnection: (connection) => {
580
- // create and start the language client
581
- // const languageClient = createLanguageClient(connection);
582
- const languageClient = new MonacoLanguageClient({
583
- name: 'Language Client',
584
- clientOptions: {
585
- // use a language id as a document selector
586
- // documentSelector: [lan],
587
- // documentSelector: [{ language: 'ruby', pattern: '**∕*.rb' }],
588
- documentSelector: ['java', 'ruby'],
589
- // disable the default error handler
590
- errorHandler: {
591
- error: () => ErrorAction.Continue,
592
- closed: () => CloseAction.DoNotRestart,
593
- },
594
- },
595
- // create a language client connection from the JSON RPC connection on demand
596
- connectionProvider: {
597
- get: (errorHandler, closeHandler) => {
598
- return Promise.resolve(
599
- createConnection(connection, errorHandler, closeHandler),
600
- );
601
- },
602
- },
603
- });
604
- const disposable = languageClient.start();
605
- connection.onClose(() => disposable.dispose());
606
- },
607
- });
608
- };
609
-
610
- const editorInit = () => {
611
- if (divEl.current) {
612
- // register Monaco languages
613
-
614
- monaco.editor.defineTheme('myCoolTheme', {
615
- base: 'vs-dark',
616
- inherit: false,
617
- rules: [
618
- {
619
- token: 'green',
620
- background: 'FF0000',
621
- foreground: '00FF00',
622
- fontStyle: 'italic',
623
- },
624
- { token: 'red', foreground: 'FF0000', fontStyle: 'bold underline' },
625
- ],
626
- colors: {
627
- 'editor.foreground': '#FFFFFF',
628
- 'editor.background': '#000000',
629
- },
630
- });
631
-
632
- // create Monaco editor
633
- editor = monaco.editor.create(divEl.current, {
634
- theme: 'vs-dark',
635
- // model: monaco.editor.createModel(
636
- // 'printF',
637
- // 'ruby',
638
- // monaco.Uri.parse('file:///index.rb'),
639
- // ),
640
- glyphMargin: true,
641
- lightbulb: {
642
- enabled: true,
643
- },
644
- });
645
-
646
- // // install Monaco language client services
647
- lspServerInject(INIT_LANGUAGE, oTStore.getState().lspServerDisabled);
648
-
649
- editorEventBinder();
650
- const editorService = editor._codeEditorService;
651
- const openEditorBase = editorService.openCodeEditor.bind(editorService);
652
- editorService.openCodeEditor = async (input, source, workspacePath) => {
653
- const result = await openEditorBase(input, source);
654
- if (result === null) {
655
- // alert('intercepted');
656
- // console.log('Open definition for:', input);
657
- // console.log(
658
- // 'Corresponding model:',
659
- // monaco.editor.getModel(input.resource),
660
- // );
661
- // console.log('Source: ', source);
662
- const gotSource = monaco.editor
663
- .getModels()
664
- // .find((x) => new RegExp(path).test(x.uri.authority));
665
- .find((x) => new RegExp(input.resource.path).test(x.uri.path));
666
- const { CRDTInfo, setCRDTInfo } = oTStore.getState();
667
- setCRDTInfo({
668
- ...CRDTInfo,
669
- file: {
670
- action: 'Get',
671
- value: gotSource.getValue(),
672
- path: gotSource.uri.path.replace(APP_DIR, ''),
673
- },
674
- });
675
- OTSTATE.switchDoc({
676
- value: gotSource.getValue(),
677
- path: gotSource.uri.path.replace(APP_DIR, ''),
678
- });
679
- }
680
- return result; // always return the base result
681
- };
682
- }
683
-
684
- window.ot = ot;
685
- };
686
-
687
- useEffect(() => {
688
- editorInit();
689
- return () => {
690
- editor.dispose();
691
- };
692
- }, []);
693
-
694
- useEffect(() => {
695
- const { CRDTInfo, doc, serverAck, appStatus } = oTStore.getState();
696
- const { usersDelta, setUsersDelta } = useValue.getState();
697
- const callList = [];
698
- // if (!OTSTATE.CRDTInfo.revision) return;
699
- // if (!CRDTInfo.operation) return;
700
- if (!CRDTInfo.editor || CRDTInfo.editor.evtType !== 'Editor') return;
701
-
702
- if (
703
- editor &&
704
- (doc?.path === CRDTInfo?.file?.path ||
705
- CRDTInfo?.file?.path === 'singleFile')
706
- ) {
707
- const server_operation = (CRDTInfo.editor
708
- .operation as unknown) as SerializedTextOperation;
709
-
710
- const CLIENT_OPERATION = receiveOperation(
711
- CRDTInfo.editor.revision,
712
- TextOperation.fromJSON(server_operation),
713
- CRDTInfo.file.path,
714
- );
715
- // if (appStatus === 'replay') {
716
- // callList.push(CLIENT_OPERATION);
717
- // if (
718
- // !!editor.getValue().length &&
719
- // CLIENT_OPERATION.baseLength === editor.getValue().length
720
- // ) {
721
- // const m = callList.shift();
722
- // // console.log(m);
723
- // editor.setValue(m.apply(editor.getValue()));
724
- // }
725
- // return;
726
- // }
727
- // if (CLIENT_OPERATION.baseLength !== editor.getValue().length) return;
728
- // client.applyServer(TextOperation.fromJSON(server_operation));
729
- client.applyServer(CLIENT_OPERATION.operation);
730
-
731
- const pushStack = true;
732
- // const { ops } = TextOperation.fromJSON(client.receiveOperation);
733
- const { ops } = client.receiveOperation;
734
- const model = editor.getModel();
735
- let index = 0;
736
- const results = [];
737
-
738
- // ops.reduce((a, b, i) => {}, []);
739
-
740
- ops.forEach((op) => {
741
- if (TextOperation.isRetain(op)) {
742
- index += op;
743
- }
744
-
745
- if (TextOperation.isInsert(op)) {
746
- const insert = model.getPositionAt(index);
747
- const originResult = {
748
- forceMoveMarkers: true,
749
- range: new monaco.Range(
750
- insert.lineNumber,
751
- insert.column,
752
- insert.lineNumber,
753
- insert.column,
754
- ),
755
- text: op,
756
- };
757
-
758
- results.push(originResult);
759
- }
760
-
761
- if (TextOperation.isDelete(op)) {
762
- const start = model.getPositionAt(index);
763
- const end = model.getPositionAt(index - op);
764
-
765
- results.push({
766
- forceMoveMarkers: false,
767
- range: new monaco.Range(
768
- start.lineNumber,
769
- start.column,
770
- end.lineNumber,
771
- end.column,
772
- ),
773
- text: null,
774
- });
775
- index -= op;
776
- }
777
- });
778
-
779
- // 全局 undo redo stack
780
- if (pushStack) {
781
- model.pushEditOperations([], results, null);
782
- } else {
783
- model.applyEdits(results);
784
- }
785
- }
786
- }, [OTSTATE.CRDTInfo]);
787
-
788
- useEffect(() => {
789
- if (!editor) return;
790
- const { CRDTInfo, doc, serverAck, appStatus } = oTStore.getState();
791
- const { usersDelta, setUsersDelta } = useValue.getState();
792
- // if (!IsMe(CRDTInfo.userInfo)) {
793
- const model = editor.getModel();
794
- // console.log(CRDTInfo, '回放');
795
-
796
- if (doc?.path === CRDTInfo?.file?.path) {
797
- if (CRDTInfo.selection) {
798
- // console.log('selection move');
799
- usersDelta.forEach((u) => {
800
- // eslint-disable-next-line prefer-const
801
- let timer;
802
- const _label = document.querySelector<HTMLElement>(
803
- `.${u.role}-label`,
804
- );
805
- timer && clearTimeout(timer);
806
-
807
- if (!_label.classList.contains('label-visible')) {
808
- _label.classList.add('label-visible');
809
- }
810
-
811
- timer = setTimeout(() => {
812
- _label.classList.remove('label-visible');
813
- }, 8000);
814
- editor.layoutContentWidget({
815
- ...u.label,
816
- getPosition: function () {
817
- return {
818
- position: {
819
- lineNumber: CRDTInfo.selection[0][7],
820
- column: CRDTInfo.selection[0][6],
821
- },
822
- preference: [
823
- monaco.editor.ContentWidgetPositionPreference.ABOVE,
824
- monaco.editor.ContentWidgetPositionPreference.BELOW,
825
- ],
826
- };
827
- },
828
- });
829
- });
830
- // evt.selection.startLineNumber,
831
- // evt.selection.startColumn,
832
- // evt.selection.endLineNumber,
833
- // evt.selection.endColumn,
834
- // evt.selection.selectionStartLineNumber,
835
- // evt.selection.selectionStartColumn,
836
- // evt.selection.positionColumn,
837
- // evt.selection.positionLineNumber,
838
-
839
- setUsersDelta(
840
- usersDelta.map((deltaInfo) => {
841
- if (deltaInfo.uuid === CRDTInfo.userInfo.uuid) {
842
- // console.log(CRDTInfo);
843
- return {
844
- // user: CRDTInfo.userInfo,
845
- ...deltaInfo,
846
-
847
- delta: editor.deltaDecorations(
848
- deltaInfo.delta ? deltaInfo.delta : '',
849
- CRDTInfo.selection.map((s) => ({
850
- range: new monaco.Range(s[0], s[1], s[2], s[3]),
851
- options: {
852
- isWholeLine: false,
853
- className: s[5] === s[6] ? deltaInfo.role : '',
854
- // stickiness:
855
- // monaco.editor.TrackedRangeStickiness
856
- // .NeverGrowsWhenTypingAtEdges,
857
- // linesDecorationsClassName: deltaInfo.role,
858
- inlineClassName: deltaInfo.role + '-selection',
859
- // glyphMarginClassName: 'myGlyphMarginClass',
860
- },
861
- })),
862
- ),
863
- };
864
- } else {
865
- return deltaInfo;
866
- }
867
- }),
868
- );
869
- }
870
-
871
- if (CRDTInfo?.editor?.evtType === 'Editor') {
872
- // const server_operation = (CRDTInfo.editor
873
- // .operation as unknown) as SerializedTextOperation;
874
- // const CLIENT_OPERATION = TextOperation.fromJSON(server_operation);
875
- // client.applyServer(TextOperation.fromJSON(server_operation));
876
- // const { ops } = CLIENT_OPERATION;
877
- // ops.forEach((_op) => {
878
- // const op = _op as number;
879
- // if (TextOperation.isRetain(op)) {
880
- // const _insert = model.getPositionAt(op);
881
- // // console.log(_insert);
882
- // }
883
- // });
884
- }
885
- }
886
- // }
887
- // console.log(usersDelta);
888
- }, [OTSTATE.CRDTInfo.selection]);
889
-
890
- useEffect(() => {
891
- if (!editor) return;
892
- }, [OTSTATE.fileSaved]);
893
-
894
- useEffect(() => {
895
- if (!editor) return;
896
-
897
- // OTSTATE.CRDTInfo.operation &&
898
- OTSTATE.serverAck && client.serverAck();
899
- docServer.set(file.path, {
900
- ...docServer.get(file.path),
901
- operation: client.operation,
902
- });
903
- // if (selectionAcks.length > 0) {
904
- // if (useValue.getState().selectionAcks.length > 0) {
905
- // ret1urn;
906
- // }
907
-
908
- // }
909
- // console.log('save');
910
- // if (useValue.getState().selectionAcks.length > 0) {
911
- // return;
912
- // }
913
- // io.emit('selection', JSON.stringify(crdt));
914
- }, [OTSTATE.serverAck]);
915
-
916
- useEffect(() => {
917
- const egt = /\.(\w+$)/gim.exec(file.path as string);
918
- const { CRDTInfo, doc } = oTStore.getState();
919
- if (!editor || !IsMe(CRDTInfo.userInfo)) return;
920
- if (file.path && egt) {
921
- updateLspOps({
922
- value: file.value,
923
- path: file.path,
924
- language: FExtension[egt[1]],
925
- CRDTInfo,
926
- doc,
927
- });
928
- }
929
- }, [file.path]);
930
-
931
- useEffect(() => {
932
- // const egt = /\.(\w+$)/gim.exec(file.path);
933
- // if (!egt) return;
934
- // if (!!editor && docType) {
935
- // monaco.editor.setModelLanguage(editor.getModel(), docType);
936
- // }
937
- // editor.setValue(file.value);
938
- }, [docType]);
939
-
940
- useEffect(() => {
941
- // if (!!editor) {
942
- // const _model = editor.getModel();
943
- // editor.setValue(doc ? doc : '');
944
- // _model &&
945
- // monaco.editor.setModelLanguage(
946
- // _model,
947
- // docType ? docType : FExtension[docType],
948
- // );
949
- // }
950
- }, [doc, docType]);
951
-
952
- useEffect(() => {
953
- const { usersDelta, setUsersDelta } = useValue.getState();
954
- // const { userList } = userListStore.getState();
955
-
956
- setUsersDelta(
957
- USERLISTSTORE.userList
958
- .filter((u) => !IsMe(u))
959
- .map((x) => {
960
- return {
961
- ...x,
962
- label: {
963
- domNode: null,
964
- getId: function () {
965
- return `label-${x.uuid}`;
966
- },
967
- getDomNode: function () {
968
- if (!this.domNode) {
969
- this.domNode = document.createElement('div');
970
- this.domNode.className = `monaco-label ${x.role}-label`;
971
- this.domNode.innerHTML = x.username;
972
- this.domNode.style.background = x.color;
973
- this.domNode.style.visibility = 'hidden';
974
- }
975
- return this.domNode;
976
- },
977
- getPosition: function () {
978
- return {
979
- position: {
980
- lineNumber: 1,
981
- column: 2,
982
- },
983
- preference: [
984
- monaco.editor.ContentWidgetPositionPreference.ABOVE,
985
- monaco.editor.ContentWidgetPositionPreference.BELOW,
986
- ],
987
- };
988
- },
989
- },
990
- };
991
- }),
992
- );
993
-
994
- editor &&
995
- usersDelta.forEach((x) => {
996
- // ;
997
- if (!document.querySelector(`.${x.role}-label`)) {
998
- editor.addContentWidget(x.label);
999
- }
1000
- });
1001
- }, [USERLISTSTORE.userList, file.path]);
1002
-
1003
- return (
1004
- <EditorLayout
1005
- ref={divEl}
1006
- className="editor-layout"
1007
- userList={userListStore.getState().userList}
1008
- ></EditorLayout>
1009
- );
1010
- };