Skip to content

Commit

Permalink
Merge pull request #73 from nextcloud/feat/custom-web-embed
Browse files Browse the repository at this point in the history
use NcReferenceList in whiteboard
  • Loading branch information
juliusknorr authored Aug 6, 2024
2 parents 1d85294 + b0c97fe commit 57755e1
Show file tree
Hide file tree
Showing 8 changed files with 1,986 additions and 10 deletions.
1,860 changes: 1,851 additions & 9 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@nextcloud/initial-state": "^2.2.0",
"@nextcloud/l10n": "^3.1.0",
"@nextcloud/router": "^3.0.1",
"@nextcloud/vue": "^8.14.0",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"jsonwebtoken": "^9.0.2",
Expand Down
29 changes: 28 additions & 1 deletion src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,35 @@
}
}

.widgets--list{
height: 100%;
}

.widgets--list > div{
height: 100% !important;
}

.widgets--list > div > div{
height: 100% !important;
}

.widget-custom {
height: 100%;
margin: 0 !important;
}

.widget-file--interactive{
height: 100% !important;
max-height: 100% !important;
min-height: unset !important;
}

.text-menubar--ready{
backdrop-filter: unset !important;
-webkit-backdrop-filter: unset !important;
}

.App {
text-align: center;
position: relative;
height: 100%;
width: 100%;
Expand Down
3 changes: 3 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type {
ExcalidrawInitialDataState,
} from '@excalidraw/excalidraw/types/types'
import { Collab } from './collaboration/collab'
import Embeddable from './Embeddable'
import type { ResolvablePromise } from '@excalidraw/excalidraw/types/utils'
import type { NonDeletedExcalidrawElement } from '@excalidraw/excalidraw/types/element/types'
interface WhiteboardAppProps {
Expand Down Expand Up @@ -126,6 +127,8 @@ export default function App({ fileId, isEmbedded }: WhiteboardAppProps) {
<div className="App">
<div className="excalidraw-wrapper">
<Excalidraw
validateEmbeddable={() => true}
renderEmbeddable={ Embeddable }
excalidrawAPI={(api: ExcalidrawImperativeAPI) => {
console.log(api)
console.log('Setting API')
Expand Down
16 changes: 16 additions & 0 deletions src/Embeddable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { NcReferenceList } from '@nextcloud/vue/dist/Components/NcRichText.js'

import VueWrapper from './VueWrapper'

/**
*
* @param props componentProps and component to be rendered in Vue
*/
export default function(props) {
const referenceProps = { text: props.link, limit: 1, interactive: true }
return React.createElement(VueWrapper, { componentProps: referenceProps, component: NcReferenceList })
}
50 changes: 50 additions & 0 deletions src/VueWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import Vue from 'vue'

const VueWrapper = function(
{ componentProps, component }) {
const vueRef = React.useRef(null)
const [vueInstance, setVueInstance] = React.useState(undefined)

React.useEffect(() => {
/**
*
*/
async function createVueInstance() {
}

createVueInstance()

setVueInstance(new Vue({
el: vueRef.current,
data() {
return {
props: componentProps,
}
},
render(h) {
return h(component, {
props: this.props,
})
},
}))

return () => {
vueInstance?.$destroy()
}
}, [])

React.useEffect(() => {
if (vueInstance) {
const keys = Object.keys(componentProps)
keys.forEach(key => { vueInstance.props[key] = componentProps[key] })
}
}, [Object.values(componentProps)])

return <div id="vue-component" ref={vueRef}></div>
}

export default VueWrapper
37 changes: 37 additions & 0 deletions src/collaboration/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import type { ExcalidrawElement } from '@excalidraw/excalidraw/types/element/types'
import type { AppState } from '@excalidraw/excalidraw/types/types'
import { isObject } from 'lodash'

/**
* Hashes elements' versionNonce (using djb2 algo). Order of elements matters.
Expand All @@ -16,6 +17,35 @@ export const hashElementsVersion = (
return elements.reduce((acc, el) => acc + el.version, 0)
}

/**
*
* @param obj1 object 1 to compare
* @param obj2 object 2 to compare
* @param exceptions keys that are not required to be equal
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isDeepEqual(obj1:any, obj2: any, exceptions: Array<string>) {

const keys1 = Object.keys(obj1)
const keys2 = Object.keys(obj2)

if (keys1.length !== keys2.length) return false

for (const key of keys1) {
const val1 = obj1[key]
const val2 = obj2[key]

const areObjects = isObject(val1) && isObject(val2)

if ((areObjects && !isDeepEqual(val1, val2, exceptions)) || (!areObjects && val1 !== val2)) {
if (!exceptions.includes(key)) {
return false
}
}
}
return true
}

/**
* decides if remote or local element should be kept
* @param localAppState state of the app
Expand All @@ -38,6 +68,13 @@ export function shouldDiscardRemoteElement(localAppState: Readonly<AppState>, lo
) {
return true
}

// embeddables get updated a lot by the excalidraw library when collaboration is active
// we need to filter out useless updates to not rerender every millisecond.
// current master of the excalidraw library probably fixes this issue but it's not available in excalidraw@latest (0.17.6)
if (localElement && localElement.type === 'embeddable' && isDeepEqual(localElement, remoteElement, ['versionNonce', 'version', 'updated', 'validated'])) {
return true
}
return false
}

Expand Down
Empty file removed src/register.ts
Empty file.

0 comments on commit 57755e1

Please sign in to comment.