Skip to content

Commit

Permalink
[#55805] Show people editing the document
Browse files Browse the repository at this point in the history
  • Loading branch information
MaciejWas authored and mgielda committed Mar 14, 2024
1 parent ea5588b commit 76eabac
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 6 deletions.
11 changes: 8 additions & 3 deletions src/MystEditor.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { render } from 'preact';
import { useState, useEffect } from 'preact/hooks';
import { useState, useEffect, useReducer } from 'preact/hooks';
import { html } from 'htm/preact';
import { StyleSheetManager, styled } from 'styled-components';

Expand All @@ -11,6 +11,7 @@ import Preview from './components/Preview';
import Diff from './components/Diff';
import { resetCache } from './hooks/markdownReplacer';
import { useText } from './hooks/useText';
import Avatars from './components/Avatars';

if (!window.myst_editor?.isFresh) {
resetCache();
Expand Down Expand Up @@ -121,12 +122,15 @@ const MystEditor = ({
collaboration = {},
spellcheckOpts = { dict: "en_US", dictionaryPath: "/dictionaries" },
customRoles = [],
transforms = []
transforms = [],
// this will create a bogus random avatar when no specific getAvatar function is provided
getAvatar = (login) => `https://secure.gravatar.com/avatar/${login}?s=30&d=identicon`,
}) => {
const [mode, setMode] = useState(initialMode);
const [fullscreen, setFullscreen] = useState(false);
const text = useText(initialText, transforms, customRoles);
const [alert, setAlert] = useState(null);
const [users, setUsers] = useReducer((_, currentUsers) => currentUsers.map(u => ({...u, avatarUrl: getAvatar(u.login)})), []);

const alertFor = (alertText, secs) => {
setAlert(alertText);
Expand Down Expand Up @@ -162,14 +166,15 @@ const MystEditor = ({
${alert && html`<${Alert}> ${alert} <//>`}
<//>
<${TopbarRight}>
<${Avatars} users=${users}/>
<${TopbarButton} type="button" onClick=${(event) => printCallback(event)}>Export as PDF<//>
<${TemplateManager} text=${text} templatelist=${templatelist} />
<${Separator} />
<${ButtonGroup} buttons=${buttonsRight} clickedId=${2} clickCallback=${(newMode) => setMode(newMode)}/>
<//>
<//>
<${MystWrapper} fullscreen=${fullscreen}>
<${CodeMirror} mode=${mode} text=${text} name=${name} id=${id} collaboration=${collaboration} spellcheckOpts=${spellcheckOpts} highlights=${transforms}/>
<${CodeMirror} setUsers=${setUsers} mode=${mode} text=${text} name=${name} id=${id} collaboration=${collaboration} spellcheckOpts=${spellcheckOpts} highlights=${transforms}/>
<${Preview} $mode=${mode} dangerouslySetInnerHTML=${{ __html: text.renderAndSanitize() }}/>
${mode === 'Diff' ? html`<${Diff} oldText=${initialText} text=${text}/>` : "" }
<//>
Expand Down
30 changes: 30 additions & 0 deletions src/components/Avatars.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { html, h } from 'htm/preact';
import { styled } from 'styled-components';

const AvatarsWrapper = styled.div`
width: 200px;
.avatar {
border-radius: 50%;
margin-top: 5px;
float: right;
border: 3px solid;
margin: 5px 0px 5px 5px;
}`

const Avatar = ({ login, color, avatarUrl }) => html`
<img src=${avatarUrl}
key=${login}
class="avatar"
style="border-color: ${color}"
/>`

const Avatars = ({ users }) => html`
<${AvatarsWrapper}>
${users.map(user =>
html`<${Avatar} ...${user}/>`
)}
<//>`;


export default Avatars
6 changes: 3 additions & 3 deletions src/components/CodeMirror.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ const setEditorText = (editor, text) => {
});
}

const CodeMirror = ({ text, id, name, className, mode, collaboration, spellcheckOpts, highlights }) => {
const CodeMirror = ({ text, id, name, className, mode, collaboration, spellcheckOpts, highlights, setUsers }) => {
const editorRef = useRef(null);
const [initialized, setInitialized] = useState(false);

Expand Down Expand Up @@ -172,8 +172,8 @@ const CodeMirror = ({ text, id, name, className, mode, collaboration, spellcheck
}

text.onSync(currentText => setEditorText(editorRef.current, currentText))

ycomments?.updateMainCodeMirror();
ycomments?.updateMainCodeMirror();
provider.watchCollabolators(setUsers)
}, [ready, initialized]);

return html`
Expand Down
11 changes: 11 additions & 0 deletions src/hooks/useCollaboration.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ import * as awarenessProtocol from "y-protocols/awareness.js";
import { WebsocketProvider } from 'y-websocket';
import { useMemo, useState } from "preact/hooks";

WebsocketProvider.prototype.watchCollabolators = function (hook) {
this.awareness.on('change', ({ added, removed }) => {
if (added || removed) {
let collabolators = Array.from(this.awareness.states)
.map(([key, { user }]) => ({ login: user.name, color: user.color }))
.reduce((curr, data) => { curr[data.login] = data; return curr }, {});
hook(Object.values(collabolators));
}
});
}

export default function useCollaboration(settings) {
if (!settings.enabled) {
return {};
Expand Down

0 comments on commit 76eabac

Please sign in to comment.