Feature style (#627)

* initial

* style: style and remove Svg export

* tiny up

Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This commit is contained in:
chlbri 2022-03-24 09:05:35 +00:00 committed by GitHub
parent 8aa54f4d8c
commit 4d5a929366
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 79 additions and 81 deletions

View file

@ -1,28 +1,26 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-non-null-assertion */
import * as React from 'react' import { TDDocument, TDFile, Tldraw, TldrawApp } from '@tldraw/tldraw'
import { Tldraw, TldrawApp, TDFile, TDDocument } from '@tldraw/tldraw' import { FC, useCallback, useEffect, useRef } from 'react'
import { vscode } from './utils/vscode'
import { defaultDocument } from './utils/defaultDocument'
import type { MessageFromExtension, MessageFromWebview } from './types'
import { exportToImage } from 'utils/export' import { exportToImage } from 'utils/export'
import type { MessageFromExtension, MessageFromWebview } from './types'
import { defaultDocument } from './utils/defaultDocument'
import { vscode } from './utils/vscode'
// Will be placed in global scope by extension // Will be placed in global scope by extension
declare let currentFile: TDFile declare let currentFile: TDFile
export default function App(): JSX.Element { const App: FC = () => {
const rLoaded = React.useRef(false) const rLoaded = useRef(false)
const rTldrawApp = React.useRef<TldrawApp>() const rTldrawApp = useRef<TldrawApp>()
const rInitialDocument = React.useRef<TDDocument>( const rInitialDocument = useRef<TDDocument>(currentFile ? currentFile.document : defaultDocument)
currentFile ? currentFile.document : defaultDocument
)
// When the editor mounts, save the state instance in a ref. // When the editor mounts, save the state instance in a ref.
const handleMount = React.useCallback((app: TldrawApp) => { const handleMount = useCallback((app: TldrawApp) => {
rTldrawApp.current = app rTldrawApp.current = app
}, []) }, [])
// When the editor's document changes, post the stringified document to the vscode extension. // When the editor's document changes, post the stringified document to the vscode extension.
const handlePersist = React.useCallback((app: TldrawApp) => { const handlePersist = useCallback((app: TldrawApp) => {
vscode.postMessage({ vscode.postMessage({
type: 'editorUpdated', type: 'editorUpdated',
text: JSON.stringify({ text: JSON.stringify({
@ -34,7 +32,7 @@ export default function App(): JSX.Element {
}, []) }, [])
// When the file changes from VS Code's side, update the editor's document. // When the file changes from VS Code's side, update the editor's document.
React.useEffect(() => { useEffect(() => {
function handleMessage({ data }: MessageEvent<MessageFromExtension>) { function handleMessage({ data }: MessageEvent<MessageFromExtension>) {
if (data.type === 'openedFile') { if (data.type === 'openedFile') {
try { try {
@ -73,3 +71,5 @@ export default function App(): JSX.Element {
</div> </div>
) )
} }
export default App

View file

@ -1,8 +1,8 @@
import React from 'react'
import * as gtag from 'utils/gtag'
import { Tldraw, TldrawApp, TldrawProps, useFileSystem } from '@tldraw/tldraw' import { Tldraw, TldrawApp, TldrawProps, useFileSystem } from '@tldraw/tldraw'
import { useAccountHandlers } from 'hooks/useAccountHandlers' import { useAccountHandlers } from 'hooks/useAccountHandlers'
import React, { FC } from 'react'
import { exportToImage } from 'utils/export' import { exportToImage } from 'utils/export'
import * as gtag from 'utils/gtag'
declare const window: Window & { app: TldrawApp } declare const window: Window & { app: TldrawApp }
@ -12,12 +12,12 @@ interface EditorProps {
isSponsor?: boolean isSponsor?: boolean
} }
export default function Editor({ const Editor: FC<EditorProps & Partial<TldrawProps>> = ({
id = 'home', id = 'home',
isUser = false, isUser = false,
isSponsor = false, isSponsor = false,
...rest ...rest
}: EditorProps & Partial<TldrawProps>) { }) => {
const handleMount = React.useCallback((app: TldrawApp) => { const handleMount = React.useCallback((app: TldrawApp) => {
window.app = app window.app = app
}, []) }, [])
@ -53,3 +53,5 @@ export default function Editor({
</div> </div>
) )
} }
export default Editor

View file

@ -1,19 +1,25 @@
import * as React from 'react'
import { Tldraw, useFileSystem } from '@tldraw/tldraw'
import { createClient } from '@liveblocks/client' import { createClient } from '@liveblocks/client'
import { LiveblocksProvider, RoomProvider } from '@liveblocks/react' import { LiveblocksProvider, RoomProvider } from '@liveblocks/react'
import { Tldraw, useFileSystem } from '@tldraw/tldraw'
import { useAccountHandlers } from 'hooks/useAccountHandlers' import { useAccountHandlers } from 'hooks/useAccountHandlers'
import { styled } from 'styles'
import { useMultiplayerState } from 'hooks/useMultiplayerState'
import { exportToImage } from 'utils/export'
import { useMultiplayerAssets } from 'hooks/useMultiplayerAssets' import { useMultiplayerAssets } from 'hooks/useMultiplayerAssets'
import { useMultiplayerState } from 'hooks/useMultiplayerState'
import { FC } from 'react'
import { styled } from 'styles'
import { exportToImage } from 'utils/export'
const client = createClient({ const client = createClient({
publicApiKey: process.env.NEXT_PUBLIC_LIVEBLOCKS_PUBLIC_API_KEY || '', publicApiKey: process.env.NEXT_PUBLIC_LIVEBLOCKS_PUBLIC_API_KEY || '',
throttle: 80, throttle: 80,
}) })
export default function MultiplayerEditor({ interface Props {
roomId: string
isUser: boolean
isSponsor: boolean
}
const MultiplayerEditor: FC<Props> = ({
roomId, roomId,
isUser = false, isUser = false,
isSponsor = false, isSponsor = false,
@ -21,7 +27,7 @@ export default function MultiplayerEditor({
roomId: string roomId: string
isUser: boolean isUser: boolean
isSponsor: boolean isSponsor: boolean
}) { }) => {
return ( return (
<LiveblocksProvider client={client}> <LiveblocksProvider client={client}>
<RoomProvider id={roomId}> <RoomProvider id={roomId}>
@ -33,15 +39,7 @@ export default function MultiplayerEditor({
// Inner Editor // Inner Editor
function Editor({ function Editor({ roomId, isUser, isSponsor }: Props) {
roomId,
isUser,
isSponsor,
}: {
roomId: string
isUser: boolean
isSponsor: boolean
}) {
const fileSystemEvents = useFileSystem() const fileSystemEvents = useFileSystem()
const { onSignIn, onSignOut } = useAccountHandlers() const { onSignIn, onSignOut } = useAccountHandlers()
const { error, ...events } = useMultiplayerState(roomId) const { error, ...events } = useMultiplayerState(roomId)
@ -68,6 +66,8 @@ function Editor({
) )
} }
export default MultiplayerEditor
const LoadingScreen = styled('div', { const LoadingScreen = styled('div', {
position: 'absolute', position: 'absolute',
top: 0, top: 0,

View file

@ -1,8 +1,7 @@
import React from 'react' import { useCallback } from 'react'
export function useMultiplayerAssets() { export function useMultiplayerAssets() {
const onAssetCreate = React.useCallback( const onAssetCreate = useCallback(async (file: File, id: string): Promise<string | false> => {
async (file: File, id: string): Promise<string | false> => {
const filename = encodeURIComponent(file.name) const filename = encodeURIComponent(file.name)
const fileType = encodeURIComponent(file.type) const fileType = encodeURIComponent(file.type)
const res = await fetch(`/api/upload?file=${filename}&fileType=${fileType}`) const res = await fetch(`/api/upload?file=${filename}&fileType=${fileType}`)
@ -20,11 +19,9 @@ export function useMultiplayerAssets() {
} else { } else {
return false return false
} }
}, }, [])
[]
)
const onAssetDelete = React.useCallback(async (id: string): Promise<boolean> => { const onAssetDelete = useCallback(async (id: string): Promise<boolean> => {
// noop // noop
return true return true
}, []) }, [])

View file

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-non-null-assertion */
import * as React from 'react' import React, { useState, useRef, useCallback } from 'react'
import type { TldrawApp, TDUser, TDShape, TDBinding, TDDocument, TDAsset } from '@tldraw/tldraw' import type { TldrawApp, TDUser, TDShape, TDBinding, TDDocument, TDAsset } from '@tldraw/tldraw'
import { useRedo, useUndo, useRoom, useUpdateMyPresence } from '@liveblocks/react' import { useRedo, useUndo, useRoom, useUpdateMyPresence } from '@liveblocks/react'
import { LiveMap, LiveObject } from '@liveblocks/client' import { LiveMap, LiveObject } from '@liveblocks/client'
@ -8,23 +8,23 @@ import { LiveMap, LiveObject } from '@liveblocks/client'
declare const window: Window & { app: TldrawApp } declare const window: Window & { app: TldrawApp }
export function useMultiplayerState(roomId: string) { export function useMultiplayerState(roomId: string) {
const [app, setApp] = React.useState<TldrawApp>() const [app, setApp] = useState<TldrawApp>()
const [error, setError] = React.useState<Error>() const [error, setError] = useState<Error>()
const [loading, setLoading] = React.useState(true) const [loading, setLoading] = useState(true)
const room = useRoom() const room = useRoom()
const onUndo = useUndo() const onUndo = useUndo()
const onRedo = useRedo() const onRedo = useRedo()
const updateMyPresence = useUpdateMyPresence() const updateMyPresence = useUpdateMyPresence()
const rLiveShapes = React.useRef<LiveMap<string, TDShape>>() const rLiveShapes = useRef<LiveMap<string, TDShape>>()
const rLiveBindings = React.useRef<LiveMap<string, TDBinding>>() const rLiveBindings = useRef<LiveMap<string, TDBinding>>()
const rLiveAssets = React.useRef<LiveMap<string, TDAsset>>() const rLiveAssets = useRef<LiveMap<string, TDAsset>>()
// Callbacks -------------- // Callbacks --------------
// Put the state into the window, for debugging. // Put the state into the window, for debugging.
const onMount = React.useCallback( const onMount = useCallback(
(app: TldrawApp) => { (app: TldrawApp) => {
app.loadRoom(roomId) app.loadRoom(roomId)
app.pause() // Turn off the app's own undo / redo stack app.pause() // Turn off the app's own undo / redo stack
@ -35,7 +35,7 @@ export function useMultiplayerState(roomId: string) {
) )
// Update the live shapes when the app's shapes change. // Update the live shapes when the app's shapes change.
const onChangePage = React.useCallback( const onChangePage = useCallback(
( (
app: TldrawApp, app: TldrawApp,
shapes: Record<string, TDShape | undefined>, shapes: Record<string, TDShape | undefined>,
@ -78,7 +78,7 @@ export function useMultiplayerState(roomId: string) {
) )
// Handle presence updates when the user's pointer / selection changes // Handle presence updates when the user's pointer / selection changes
const onChangePresence = React.useCallback( const onChangePresence = useCallback(
(app: TldrawApp, user: TDUser) => { (app: TldrawApp, user: TDUser) => {
updateMyPresence({ id: app.room?.userId, user }) updateMyPresence({ id: app.room?.userId, user })
}, },

View file

@ -1,9 +1,9 @@
import dynamic from 'next/dynamic'
import type { GetServerSideProps } from 'next' import type { GetServerSideProps } from 'next'
import { getSession } from 'next-auth/react' import { getSession } from 'next-auth/react'
import dynamic from 'next/dynamic'
import Head from 'next/head' import Head from 'next/head'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useMemo } from 'react' import { FC, useMemo } from 'react'
const Editor = dynamic(() => import('components/Editor'), { ssr: false }) const Editor = dynamic(() => import('components/Editor'), { ssr: false })
@ -12,7 +12,7 @@ interface PageProps {
isSponsor: boolean isSponsor: boolean
} }
export default function Home({ isUser, isSponsor }: PageProps): JSX.Element { const Home: FC<PageProps> = ({ isUser, isSponsor }) => {
const { query } = useRouter() const { query } = useRouter()
const isExportMode = useMemo(() => 'exportMode' in query, [query]) const isExportMode = useMemo(() => 'exportMode' in query, [query])
@ -26,6 +26,8 @@ export default function Home({ isUser, isSponsor }: PageProps): JSX.Element {
) )
} }
export default Home
export const getServerSideProps: GetServerSideProps = async (context) => { export const getServerSideProps: GetServerSideProps = async (context) => {
const session = await getSession(context) const session = await getSession(context)

View file

@ -1,11 +1,11 @@
import { styled } from 'styles'
import { getSession, signIn, signOut, useSession } from 'next-auth/react'
import type { GetServerSideProps } from 'next' import type { GetServerSideProps } from 'next'
import Link from 'next/link' import { getSession, signIn, signOut, useSession } from 'next-auth/react'
import React from 'react'
import Head from 'next/head' import Head from 'next/head'
import Link from 'next/link'
import React, { FC } from 'react'
import { styled } from 'styles'
export default function Sponsorware(): JSX.Element { const Sponsorware: FC = () => {
const { data, status } = useSession() const { data, status } = useSession()
return ( return (
@ -86,6 +86,8 @@ export default function Sponsorware(): JSX.Element {
) )
} }
export default Sponsorware
export const getServerSideProps: GetServerSideProps = async (context) => { export const getServerSideProps: GetServerSideProps = async (context) => {
const session = await getSession(context) const session = await getSession(context)

View file

@ -1,5 +0,0 @@
import { Utils } from './utils'
export { Utils } from './utils'
export { Svg } from './svg'
export default Utils
//# sourceMappingURL=index.d.ts.map