vzcode 0.20.1 → 0.21.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.
package/dist/index.html CHANGED
@@ -28,8 +28,8 @@
28
28
  href="https://unpkg.com/bootstrap@5.3.0/dist/css/bootstrap.min.css"
29
29
  rel="stylesheet"
30
30
  />
31
- <script type="module" crossorigin src="/assets/index-12dbf516.js"></script>
32
- <link rel="stylesheet" href="/assets/index-0053b846.css">
31
+ <script type="module" crossorigin src="/assets/index-37015623.js"></script>
32
+ <link rel="stylesheet" href="/assets/index-1547f7b8.css">
33
33
  </head>
34
34
  <body>
35
35
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vzcode",
3
- "version": "0.20.1",
3
+ "version": "0.21.0",
4
4
  "description": "Multiplayer code editor system",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -28,6 +28,7 @@ import { usePrettier } from './usePrettier';
28
28
  import PrettierWorker from './usePrettier/worker?worker';
29
29
  import { SplitPaneResizeProvider } from './SplitPaneResizeContext';
30
30
  import { Resizer } from './Resizer';
31
+ import { PresenceNotifications } from './PresenceNotifications';
31
32
  import './style.scss';
32
33
 
33
34
  // Instantiate the Prettier worker.
@@ -307,6 +308,9 @@ function App() {
307
308
  editorCache={editorCache}
308
309
  />
309
310
  ) : null}
311
+ <PresenceNotifications
312
+ docPresence={docPresence}
313
+ />
310
314
  </div>
311
315
  <Resizer />
312
316
  </div>
@@ -1,4 +1,5 @@
1
1
  import { EditorView } from 'codemirror';
2
+ import { username } from '../Settings.tsx';
2
3
 
3
4
  // Deals with broadcasting changes in cursor location and selection.
4
5
  export const json1PresenceBroadcast = ({
@@ -22,6 +23,7 @@ export const json1PresenceBroadcast = ({
22
23
  const presence = {
23
24
  start: [...path, from],
24
25
  end: [...path, to],
26
+ username: username,
25
27
  };
26
28
 
27
29
  // Broadcast presence to remote clients!
@@ -32,13 +32,16 @@ export const json1PresenceDisplay = ({
32
32
  // Receive remote presence changes.
33
33
  docPresence.on('receive', (id, presence) => {
34
34
  // If presence === null, the user has disconnected / exited
35
+ // notification(presence);
36
+ // console.log('docPresence in presenceDisplay:',docPresence);
37
+ // console.log('presence in presenceDisplay:', presence);
38
+
35
39
  // We also check if the presence is for the current file or not.
36
40
  if (presence && pathMatches(path, presence)) {
37
41
  presenceState[id] = presence;
38
42
  } else {
39
43
  delete presenceState[id];
40
44
  }
41
-
42
45
  // Update decorations to reflect new presence state.
43
46
  // TODO consider mutating this rather than recomputing it on each change.
44
47
  this.decorations = Decoration.set(
@@ -99,6 +102,47 @@ export const json1PresenceDisplay = ({
99
102
  presenceTheme,
100
103
  ];
101
104
 
105
+ // const notification = (presence) => {
106
+ // const notif = document.createElement('div');
107
+ // notif.className = 'notification-presence';
108
+ // if (presence === null){
109
+ // notif.textContent = 'User asdfgasdfgasdfg left the collaboration session.';
110
+ // notif.style.display = 'block';
111
+ // }
112
+ // // The following causes the popup to show every time the remote cursor moves
113
+ // // to a different location on the file and not when the user first joins
114
+ // // else {
115
+ // // notif.textContent = presence + 'joined the collaboration session.';
116
+ // // notif.style.display = 'block';
117
+ // // }
118
+ // document.body.appendChild(notif);
119
+
120
+ // const notifStyle = document.createElement('style');
121
+ // notifStyle.innerText = `
122
+ // .notification-presence {
123
+ // position: fixed;
124
+ // display: none;
125
+ // bottom: 20px;
126
+ // right: 20px;
127
+ // max-width: 300px;
128
+ // overflow-x: hidden;
129
+ // white-space: nowrap;
130
+ // background-color: rgb(54, 65, 89);
131
+ // color: rgb(154, 160, 172);
132
+ // padding: 15px;
133
+ // }
134
+ // .notification-presence:hover {
135
+ // overflow-x: auto;
136
+ // }`;
137
+ // document.head.appendChild(notifStyle);
138
+
139
+ // setTimeout(() => {
140
+ // notif.style.display = 'none';
141
+ // }, 10000);
142
+
143
+ // return notif;
144
+ // };
145
+
102
146
  const presenceAnnotation = Annotation.define();
103
147
 
104
148
  // Checks that the path of this file
@@ -0,0 +1,128 @@
1
+ import { useState, useEffect } from 'react';
2
+ import './style.scss';
3
+
4
+ // A presence notification is a message that is displayed when a user joins or leaves a session.
5
+ // It has the following properties:
6
+ // - `user` is the username of the user who joined or left the session.
7
+ // - `join` is a boolean value that indicates whether the user joined or left the session.
8
+ // - `true` means user has joined the session.
9
+ // - `false` means user has left the session.
10
+ type PresenceNotification = {
11
+ user: string;
12
+ join: boolean;
13
+ presenceId: string;
14
+ };
15
+
16
+ export const PresenceNotifications = ({
17
+ docPresence,
18
+ }: {
19
+ docPresence?: any;
20
+ }) => {
21
+ const [presenceNotifications, setPresenceNotifications] =
22
+ useState<Array<PresenceNotification>>([]);
23
+
24
+ // // console.log('docPresence:', docPresence);
25
+ // const [visible, setVisible] = useState(true);
26
+ // const [user, setUser] = useState('');
27
+
28
+ // // `true` means user has joined the session.
29
+ // // `false` means user has left the session.
30
+ // const [join, setJoin] = useState<boolean>(true);
31
+
32
+ useEffect(() => {
33
+ // console.log('useEffect triggered.');
34
+ if (docPresence) {
35
+ // See https://share.github.io/sharedb/presence
36
+ docPresence.on('receive', (presenceId, update) => {
37
+ // TODO figure out how to get username from `presenceId`.
38
+ const user = 'someone';
39
+
40
+ // `true` means user has joined the session.
41
+ // `false` means user has left the session.
42
+ const join = update === null;
43
+
44
+ // Add an entry to the presence notifications array.
45
+ setPresenceNotifications((prev) => [
46
+ ...prev,
47
+ { user, join, presenceId },
48
+ ]);
49
+
50
+ // Remove it after 5 seconds.
51
+ setTimeout(() => {
52
+ setPresenceNotifications((prev) =>
53
+ prev.filter(
54
+ (notification) =>
55
+ notification.presenceId !== presenceId,
56
+ ),
57
+ );
58
+ }, 5000);
59
+ });
60
+
61
+ // console.log('inside if of useEffect.');
62
+ // docPresence.on('receive', (presence) => {
63
+ // console.log('presence', presence);
64
+
65
+ // // Add an entry to the presence notifications array.
66
+ // setPresenceNotifications((prev) => [
67
+ // ...prev,
68
+ // { user: presence.username, join: presence === null },
69
+ // ]);
70
+
71
+ // console.log('receive triggered.');
72
+ // if (presence === null) {
73
+ // setJoin(false);
74
+ // }
75
+ // const { username } = presence;
76
+ // setUser(username);
77
+ // });
78
+
79
+ // const timer = setTimeout(() => {
80
+ // setVisible(false);
81
+ // }, 10000);
82
+ return () => {
83
+ // clearTimeout(timer);
84
+ };
85
+ } else {
86
+ // setVisible(false);
87
+ }
88
+ }, [docPresence]);
89
+
90
+ console.log(
91
+ 'presenceNotifications',
92
+ presenceNotifications,
93
+ );
94
+
95
+ return presenceNotifications.length > 0 ? (
96
+ <div className="vz-notification">
97
+ {presenceNotifications.map((notification) => {
98
+ const { user, join } = notification;
99
+ return (
100
+ <div
101
+ key={notification.presenceId}
102
+ className="vz-notification-item"
103
+ >
104
+ {join
105
+ ? `${user} has joined the session.`
106
+ : `${user} has left the session.`}
107
+ </div>
108
+ );
109
+ })}
110
+ </div>
111
+ ) : null;
112
+ // return null;
113
+
114
+ // return (
115
+ // <Modal
116
+ // className="vz-notification"
117
+ // show={visible}
118
+ // onHide={() => setVisible(false)}
119
+ // animation={false}
120
+ // >
121
+ // <Modal.Body>
122
+ // {join
123
+ // ? `${user} has joined the session.`
124
+ // : `${user} has left the session.`}
125
+ // </Modal.Body>
126
+ // </Modal>
127
+ // );
128
+ };
@@ -0,0 +1,17 @@
1
+ .vz-notification {
2
+ position: fixed;
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: 10px;
6
+ bottom: 20px;
7
+ right: 20px;
8
+
9
+ color: rgb(154, 160, 172);
10
+ padding: 15px;
11
+
12
+ .vz-notification-item {
13
+ background-color: rgb(54, 65, 89);
14
+ padding: 5px;
15
+ border-radius: 5px;
16
+ }
17
+ }
@@ -1,4 +1,4 @@
1
- import { useCallback } from 'react';
1
+ import { useCallback, useRef } from 'react';
2
2
  import { Button, Modal, Form } from './bootstrap';
3
3
  import Select from 'react-select';
4
4
  import {
@@ -14,6 +14,8 @@ const saveTimes = [
14
14
  { value: 30, label: '30 seconds' },
15
15
  ];
16
16
 
17
+ export let username = 'Anonymous';
18
+
17
19
  export const Settings = ({
18
20
  show,
19
21
  onClose,
@@ -43,6 +45,12 @@ export const Settings = ({
43
45
  [],
44
46
  );
45
47
 
48
+ const usernameRef = useRef<HTMLInputElement>(null);
49
+ const handleUsernameChange = () => {
50
+ const usernameValue = usernameRef.current?.value;
51
+ username = usernameValue;
52
+ };
53
+
46
54
  return show ? (
47
55
  <Modal
48
56
  className="vz-settings"
@@ -58,6 +66,8 @@ export const Settings = ({
58
66
  <Form.Label>Username</Form.Label>
59
67
  <Form.Control
60
68
  type="text"
69
+ ref={usernameRef}
70
+ onChange={handleUsernameChange}
61
71
  placeholder="Enter username"
62
72
  />
63
73
  <Form.Text className="text-muted">
@@ -45,6 +45,7 @@ export const FileListing = ({
45
45
  handleDeleteClick={handleDeleteClick}
46
46
  handleRenameClick={handleRenameClick}
47
47
  isDir={false}
48
+ name={name}
48
49
  >
49
50
  {name}
50
51
  </Item>