Skip to content

Commit

Permalink
Merge pull request #200 from nextcloud/feat/support-translation
Browse files Browse the repository at this point in the history
support translation
  • Loading branch information
juliushaertl authored Oct 8, 2024
2 parents e5c8ac8 + 5cf3b9c commit 9fdbd14
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 20 deletions.
66 changes: 46 additions & 20 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,21 @@ import Embeddable from './Embeddable'
import type { ResolvablePromise } from '@excalidraw/excalidraw/types/utils'
import type { NonDeletedExcalidrawElement } from '@excalidraw/excalidraw/types/element/types'
import { getLinkWithPicker } from '@nextcloud/vue/dist/Components/NcRichText.js'
import { useExcalidrawLang } from './hooks/useExcalidrawLang'

interface WhiteboardAppProps {
fileId: number;
fileName: string;
isEmbedded: boolean;
publicSharingToken: string | null;
fileId: number
fileName: string
isEmbedded: boolean
publicSharingToken: string | null
}

export default function App({ fileId, isEmbedded, fileName, publicSharingToken }: WhiteboardAppProps) {
export default function App({
fileId,
isEmbedded,
fileName,
publicSharingToken,
}: WhiteboardAppProps) {
const fileNameWithoutExtension = fileName.split('.').slice(0, -1).join('.')

const [viewModeEnabled] = useState(isEmbedded)
Expand All @@ -44,13 +51,19 @@ export default function App({ fileId, isEmbedded, fileName, publicSharingToken }

const isDarkMode = () => {
const ncThemes = document.body.dataset?.themes
return (window.matchMedia('(prefers-color-scheme: dark)').matches && ncThemes?.indexOf('light') === -1)
return (
(window.matchMedia('(prefers-color-scheme: dark)').matches
&& ncThemes?.indexOf('light') === -1)
|| ncThemes?.indexOf('dark') > -1
)
}
const [theme, setTheme] = useState(isDarkMode() ? 'dark' : 'light')

const lang = useExcalidrawLang()

useEffect(() => {
const themeChangeListener = () => setTheme(isDarkMode() ? 'dark' : 'light')
const themeChangeListener = () =>
setTheme(isDarkMode() ? 'dark' : 'light')
const mq = window.matchMedia('(prefers-color-scheme: dark)')
mq.addEventListener('change', themeChangeListener)
return () => {
Expand All @@ -69,26 +82,29 @@ export default function App({ fileId, isEmbedded, fileName, publicSharingToken }
}

const initialStatePromiseRef = useRef<{
promise: ResolvablePromise<ExcalidrawInitialDataState | null>;
promise: ResolvablePromise<ExcalidrawInitialDataState | null>
}>({ promise: null! })
if (!initialStatePromiseRef.current.promise) {
initialStatePromiseRef.current.promise = resolvablePromise()
}

const [
excalidrawAPI,
setExcalidrawAPI,
] = useState<ExcalidrawImperativeAPI | null>(null)
const [excalidrawAPI, setExcalidrawAPI]
= useState<ExcalidrawImperativeAPI | null>(null)
const [collab, setCollab] = useState<Collab | null>(null)

if (excalidrawAPI && !collab) setCollab(new Collab(excalidrawAPI, fileId, publicSharingToken))
if (excalidrawAPI && !collab) { setCollab(new Collab(excalidrawAPI, fileId, publicSharingToken)) }
if (collab && !collab.portal.socket) collab.startCollab()
useEffect(() => {
const extraTools = document.getElementsByClassName('App-toolbar__extra-tools-trigger')[0]
const extraTools = document.getElementsByClassName(
'App-toolbar__extra-tools-trigger',
)[0]
const smartPick = document.createElement('label')
smartPick.classList.add(...['ToolIcon', 'Shape'])
if (extraTools) {
extraTools.parentNode?.insertBefore(smartPick, extraTools.previousSibling)
extraTools.parentNode?.insertBefore(
smartPick,
extraTools.previousSibling,
)
const root = createRoot(smartPick)
root.render(renderSmartPicker())
}
Expand Down Expand Up @@ -130,7 +146,7 @@ export default function App({ fileId, isEmbedded, fileName, publicSharingToken }
(
element: NonDeletedExcalidrawElement,
event: CustomEvent<{
nativeEvent: MouseEvent | React.PointerEvent<HTMLCanvasElement>;
nativeEvent: MouseEvent | React.PointerEvent<HTMLCanvasElement>
}>,
) => {
const link = element.link!
Expand All @@ -151,11 +167,16 @@ export default function App({ fileId, isEmbedded, fileName, publicSharingToken }
const addWebEmbed = (link: string) => {
let cords: { x: any; y: any }
if (excalidrawAPI) {
cords = viewportCoordsToSceneCoords({ clientX: 100, clientY: 100 }, excalidrawAPI.getAppState())
cords = viewportCoordsToSceneCoords(
{ clientX: 100, clientY: 100 },
excalidrawAPI.getAppState(),
)
} else {
cords = { x: 0, y: 0 }
}
const elements = excalidrawAPI?.getSceneElementsIncludingDeleted().slice()
const elements = excalidrawAPI
?.getSceneElementsIncludingDeleted()
.slice()
elements?.push({
link,
id: (Math.random() + 1).toString(36).substring(7),
Expand Down Expand Up @@ -204,7 +225,12 @@ export default function App({ fileId, isEmbedded, fileName, publicSharingToken }

const renderSmartPicker = () => {
return (
<button className="dropdown-menu-button App-toolbar__extra-tools-trigger" aria-label="Smart picker" aria-keyshortcuts="0" onClick={pickFile} title='Smart picker'>
<button
className="dropdown-menu-button App-toolbar__extra-tools-trigger"
aria-label="Smart picker"
aria-keyshortcuts="0"
onClick={pickFile}
title="Smart picker">
<Icon path={mdiSlashForwardBox} size={1} />
</button>
)
Expand Down Expand Up @@ -234,7 +260,7 @@ export default function App({ fileId, isEmbedded, fileName, publicSharingToken }
},
}}
onLinkOpen={onLinkOpen}
>
langCode={lang}>
{renderMenu()}
</Excalidraw>
</div>
Expand Down
43 changes: 43 additions & 0 deletions src/hooks/useExcalidrawLang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import { useState, useEffect } from 'react'
import { getLanguage } from '@nextcloud/l10n'
import { languages } from '@excalidraw/excalidraw'

const languageMap = new Map(languages.map(lang => [lang.code.toLowerCase(), lang.code]))

function mapNextcloudToExcalidrawLang(nextcloudLang: string): string {
const lowerNextcloudLang = nextcloudLang.toLowerCase()

if (languageMap.has(lowerNextcloudLang)) {
return languageMap.get(lowerNextcloudLang)!
}

const hyphenatedLang = lowerNextcloudLang.replace('_', '-')
if (languageMap.has(hyphenatedLang)) {
return languageMap.get(hyphenatedLang)!
}

for (const [excalidrawLang, originalCode] of languageMap) {
if (excalidrawLang.startsWith(lowerNextcloudLang)
|| lowerNextcloudLang.startsWith(excalidrawLang.split('-')[0])) {
return originalCode
}
}

return 'en'
}

export function useExcalidrawLang() {
const [lang, setLang] = useState(() => mapNextcloudToExcalidrawLang(getLanguage()))

useEffect(() => {
const nextcloudLang = getLanguage()
setLang(mapNextcloudToExcalidrawLang(nextcloudLang))
}, [])

return lang
}

0 comments on commit 9fdbd14

Please sign in to comment.