Skip to content

Commit

Permalink
Merge pull request #4336 from nextcloud/enh/hide_cursors
Browse files Browse the repository at this point in the history
Fade out user cursor labels after five seconds of inactivity
  • Loading branch information
max-nextcloud committed Jul 28, 2023
2 parents 8b287aa + 7332d99 commit a573d74
Show file tree
Hide file tree
Showing 20 changed files with 119 additions and 33 deletions.
4 changes: 2 additions & 2 deletions js/editor.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/editor.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/files-modal.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion js/files-modal.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions js/highlight/q-js-js.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion js/highlight/q-js-js.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions js/text-editors.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-editors.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-files.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-files.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-public.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-public.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-text.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-text.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-viewer.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-viewer.js.map

Large diffs are not rendered by default.

15 changes: 11 additions & 4 deletions src/components/Editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ import { getCurrentUser } from '@nextcloud/auth'
import { loadState } from '@nextcloud/initial-state'
import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'
import { Collaboration } from '@tiptap/extension-collaboration'
import { CollaborationCursor } from '@tiptap/extension-collaboration-cursor'
import Autofocus from '../extensions/Autofocus.js'
import { Doc } from 'yjs'
Expand All @@ -108,7 +107,7 @@ import { createEditor, serializePlainText, loadSyntaxHighlight } from './../Edit
import { createMarkdownSerializer } from './../extensions/Markdown.js'
import markdownit from './../markdownit/index.js'
import { Keymap } from './../extensions/index.js'
import { CollaborationCursor, Keymap } from '../extensions/index.js'
import DocumentStatus from './Editor/DocumentStatus.vue'
import isMobile from './../mixins/isMobile.js'
import setContent from './../mixins/setContent.js'
Expand Down Expand Up @@ -507,6 +506,7 @@ export default {
? session.displayName
: (session?.guestName || t('text', 'Guest')),
color: session?.color,
clientId: this.$ydoc.clientID,
},
}),
Keymap.configure({
Expand Down Expand Up @@ -794,7 +794,6 @@ export default {
width: 100%;
background-color: var(--color-main-background);
}
</style>
<style lang="scss">
Expand Down Expand Up @@ -918,6 +917,14 @@ export default {
padding: 0.1rem 0.3rem;
border-radius: 3px 3px 3px 0;
white-space: nowrap;
}
opacity: 0;
&.collaboration-cursor__label__active {
opacity: 1;
}
&:not(.collaboration-cursor__label__active) {
transition: opacity 0.2s 5s;
}
}
</style>
81 changes: 81 additions & 0 deletions src/extensions/CollaborationCursor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { CollaborationCursor as TiptapCollaborationCursor } from '@tiptap/extension-collaboration-cursor'

/**
* Show cursor for client ID
* Wait 50ms for cases where the cursor gets re-rendered
*
* @param {number} clientId The Yjs client ID
*/
function showCursorLabel(clientId) {
setTimeout(() => {
const el = document.getElementById(`collaboration-cursor__label__${clientId}`)
if (!el) {
return
}

el.classList.add('collaboration-cursor__label__active')
setTimeout(() => {
el?.classList.remove('collaboration-cursor__label__active')
}, 50)
}, 50)
}

/**
* Unix timestamp in seconds.
*/
function getTimestamp() {
return Math.floor(Date.now() / 1000)
}

const CollaborationCursor = TiptapCollaborationCursor.extend({
addOptions() {
return {
provider: null,
user: {
name: null,
clientId: null,
color: null,
lastUpdate: getTimestamp(),
},
render: user => {
const cursor = document.createElement('span')

cursor.classList.add('collaboration-cursor__caret')
cursor.setAttribute('style', `border-color: ${user.color}`)

const label = document.createElement('div')

label.classList.add('collaboration-cursor__label')
label.id = `collaboration-cursor__label__${user.clientId}`
label.setAttribute('style', `background-color: ${user.color}`)
label.insertBefore(document.createTextNode(user.name), null)
cursor.insertBefore(label, null)

return cursor
},
}
},

onCreate() {
this.options.provider.awareness.on('change', ({ added, removed, updated }, origin) => {
if (origin !== 'local') {
for (const clientId of [...added, ...updated]) {
if (clientId !== this.options.user.clientId) {
showCursorLabel(clientId)
}
}
}
})
},

// Flag own cursor as active on undoable changes to the document state
onTransaction({ transaction }) {
const { updated, meta } = transaction
if (updated && (meta.addToHistory ?? true) && !meta.pointer) {
this.options.user.lastUpdate = getTimestamp()
this.options.provider.awareness.setLocalStateField('user', this.options.user)
}
},
})

export default CollaborationCursor
2 changes: 2 additions & 0 deletions src/extensions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*
*/

import CollaborationCursor from './CollaborationCursor.js'
import Emoji from './Emoji.js'
import Keymap from './Keymap.js'
import UserColor from './UserColor.js'
Expand All @@ -30,6 +31,7 @@ import KeepSyntax from './KeepSyntax.js'
import Mention from './Mention.js'

export {
CollaborationCursor,
Emoji,
Keymap,
UserColor,
Expand Down
6 changes: 1 addition & 5 deletions src/services/SyncService.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,10 @@ class SyncService {
}

sendSteps(getSendable) {
// If already retrying, do nothing.
// If already waiting to send, do nothing.
if (this.#sendIntervalId) {
return
}
if (this.connection && !this.sending) {
return this._sendSteps(getSendable)
}
// If already sending, retry every 200ms.
return new Promise((resolve, reject) => {
this.#sendIntervalId = setInterval(() => {
if (this.connection && !this.sending) {
Expand Down

0 comments on commit a573d74

Please sign in to comment.