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