feat: render selected document

This commit is contained in:
Joshua Shoemaker 2022-12-13 16:51:56 -06:00
parent 9ab224f70c
commit acf93695d3
7 changed files with 117 additions and 14 deletions

View File

@ -18,3 +18,16 @@ func GetDocumentCollection() *DocumentCollection {
func (collection *DocumentCollection) AddDocument(document Entity) { func (collection *DocumentCollection) AddDocument(document Entity) {
collection.Documents = append(collection.Documents, document) collection.Documents = append(collection.Documents, document)
} }
func (collection *DocumentCollection) GetDocumentById(id string) Entity {
var foundDocument Entity
for _, d := range collection.Documents {
if d.Id == id {
foundDocument = d
break
}
}
return foundDocument
}

View File

@ -1,5 +1,6 @@
import 'server-only' import 'server-only'
import MainHead from '../components/MainHead' import MainHead from '../components/MainHead'
import DocumentRenderer from '../components/workspace/DocumentRenderer'
import Navigation from '../components/workspace/Navigation' import Navigation from '../components/workspace/Navigation'
export default function Home() { export default function Home() {
@ -16,8 +17,8 @@ export default function Home() {
</div> </div>
<div className="mx-auto px-4 sm:px-6 md:px-8"> <div className="mx-auto px-4 sm:px-6 md:px-8">
<div className="py-4"> <div className="py-4">
<div className="h-96 rounded-lg border-4 border-dashed border-gray-200"> <div className=" min-h-96 rounded-lg border-4 border-dashed border-gray-200">
{/* Add canvas */} <DocumentRenderer />
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,44 @@
'use client'
import { useEffect, useRef } from "react"
import { useProject } from "../../context/Project/provider"
const loadImage = (path: string): Promise<HTMLImageElement> => {
return new Promise((resolve, reject) => {
const image = new Image()
image.src = path
image.onload = () => resolve(image)
image.onerror = (error) => reject(error)
})
}
const DocumentRenderer = () => {
const { getSelectedDocument } = useProject()
const canvasRef = useRef<HTMLCanvasElement>(null)
const applyDocumentToCanvas = async (path: string) => {
const image = await loadImage(path)
const canvas = canvasRef.current
if (!canvas) return
canvas.width = image.naturalWidth
canvas.height = image.naturalHeight
const context = canvas.getContext('2d')
if (!context) return
context.drawImage(image, 10, 10, image.width, image.height)
}
useEffect(() => {
const selectedDocument = getSelectedDocument()
const documentPath = selectedDocument?.path
if (documentPath) applyDocumentToCanvas(selectedDocument.path)
}, [getSelectedDocument])
return (
<canvas ref={canvasRef}></canvas>
)
}
export default DocumentRenderer

View File

@ -43,14 +43,20 @@ function classNames(...classes: any[]) {
} }
function Sidebar() { function Sidebar() {
const [selectedItemId, setSelectedItemId] = useState('')
const [selectedGroupId, setSelectedGroupId] = useState('') const [selectedGroupId, setSelectedGroupId] = useState('')
const [isAddNewDocumentInputShowing, setIsAddNewDocumentInputShowing] = useState(false) const [isAddNewDocumentInputShowing, setIsAddNewDocumentInputShowing] = useState(false)
const [isAddNewGroupInputShowing, setIsAddNewGroupInputShowing] = useState(false) const [isAddNewGroupInputShowing, setIsAddNewGroupInputShowing] = useState(false)
const addDocumentTextInput = useRef<HTMLInputElement>(null) const addDocumentTextInput = useRef<HTMLInputElement>(null)
const addGroupTextInput = useRef<HTMLInputElement>(null) const addGroupTextInput = useRef<HTMLInputElement>(null)
const { documents, groups, requestAddDocument, requestAddDocumentGroup } = useProject() const {
documents,
groups,
requestAddDocument,
requestAddDocumentGroup,
selectedDocumentId,
setSelectedDocumentId
} = useProject()
const navigation = getNavigationProps(documents, groups) const navigation = getNavigationProps(documents, groups)
@ -75,7 +81,7 @@ function Sidebar() {
} }
const onItemClickHandler = (itemId: string) => { const onItemClickHandler = (itemId: string) => {
setSelectedItemId(itemId) setSelectedDocumentId(itemId)
setSelectedGroupId(getParentGroupIdFromItemId(itemId)) setSelectedGroupId(getParentGroupIdFromItemId(itemId))
setIsAddNewDocumentInputShowing(false) setIsAddNewDocumentInputShowing(false)
setIsAddNewGroupInputShowing(false) setIsAddNewGroupInputShowing(false)
@ -96,12 +102,15 @@ function Sidebar() {
const response = await requestAddDocument(groupId, documentName) const response = await requestAddDocument(groupId, documentName)
if (!response.id) return if (!response.id) return
setSelectedItemId(response.id)
setSelectedDocumentId(response.id)
setSelectedGroupId(groupId) setSelectedGroupId(groupId)
setIsAddNewDocumentInputShowing(false) setIsAddNewDocumentInputShowing(false)
} }
const onConfirmAddGroupClickHandler = async(e: React.MouseEvent) => { const onConfirmAddGroupClickHandler = async (e: React.MouseEvent) => {
const groupName = addGroupTextInput.current?.value const groupName = addGroupTextInput.current?.value
if (!groupName) return if (!groupName) return
@ -132,7 +141,7 @@ function Sidebar() {
> >
<XMarkIcon className="h-4 w-5" aria-hidden="true" /> <XMarkIcon className="h-4 w-5" aria-hidden="true" />
</button> </button>
<button <button
type="button" type="button"
onClick={onConfirmAddGroupClickHandler} onClick={onConfirmAddGroupClickHandler}
@ -219,7 +228,7 @@ function Sidebar() {
role='button' role='button'
onClick={() => onItemClickHandler(child.id)} onClick={() => onItemClickHandler(child.id)}
className={classNames( className={classNames(
child.id === selectedItemId child.id === selectedDocumentId
? 'bg-gray-900 text-white' ? 'bg-gray-900 text-white'
: 'text-gray-300 hover:bg-gray-700 hover:text-white', : 'text-gray-300 hover:bg-gray-700 hover:text-white',
'group w-full flex items-center pr-2 py-2 text-left font-medium text-sm rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 p-2' 'group w-full flex items-center pr-2 py-2 text-left font-medium text-sm rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 p-2'

View File

@ -14,6 +14,7 @@ type Props = { children: ReactNode, projectProps: ProjectProps }
export function ProjectProvider({ children, projectProps }: Props) { export function ProjectProvider({ children, projectProps }: Props) {
const [ documents, setDocuments ] = useState<ipc.Document[]>(projectProps.documents) const [ documents, setDocuments ] = useState<ipc.Document[]>(projectProps.documents)
const [ groups, setGroups ] = useState<ipc.Group[]>(projectProps.groups) const [ groups, setGroups ] = useState<ipc.Group[]>(projectProps.groups)
const [selectedDocumentId, setSelectedDocumentId] = useState<string>('')
const updateDocuments = async () => { const updateDocuments = async () => {
GetDocuments().then(response => { GetDocuments().then(response => {
@ -35,14 +36,19 @@ export function ProjectProvider({ children, projectProps }: Props) {
return response return response
} }
const getSelectedDocument = () => documents.find(d => d.id === selectedDocumentId)
if (!documents.length || !groups.length) updateDocuments() if (!documents.length || !groups.length) updateDocuments()
const value = { const value = {
id: '', id: '',
documents, documents,
groups, groups,
getSelectedDocument,
requestAddDocument, requestAddDocument,
requestAddDocumentGroup, requestAddDocumentGroup,
selectedDocumentId,
setSelectedDocumentId,
} }
return <ProjectContext.Provider value={value}> return <ProjectContext.Provider value={value}>

View File

@ -7,6 +7,9 @@ export type ProjectProps = {
} }
export type ProjectContextType = { export type ProjectContextType = {
getSelectedDocument: () => ipc.Document | undefined
requestAddDocument: (groupId: string, documentName: string) => Promise<ipc.Document>, requestAddDocument: (groupId: string, documentName: string) => Promise<ipc.Document>,
requestAddDocumentGroup: (groupName: string) => Promise<ipc.Group>, requestAddDocumentGroup: (groupName: string) => Promise<ipc.Group>,
selectedDocumentId: string,
setSelectedDocumentId: (id: string) => void,
} & ProjectProps } & ProjectProps

37
main.go
View File

@ -2,7 +2,10 @@ package main
import ( import (
"embed" "embed"
"fmt"
"log" "log"
"net/http"
"os"
app "textualize/core/App" app "textualize/core/App"
document "textualize/core/Document" document "textualize/core/Document"
@ -11,6 +14,7 @@ import (
"github.com/wailsapp/wails/v2" "github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/logger" "github.com/wailsapp/wails/v2/pkg/logger"
"github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
"github.com/wailsapp/wails/v2/pkg/options/mac" "github.com/wailsapp/wails/v2/pkg/options/mac"
"github.com/wailsapp/wails/v2/pkg/options/windows" "github.com/wailsapp/wails/v2/pkg/options/windows"
) )
@ -18,6 +22,26 @@ import (
//go:embed frontend/out frontend/out/_next/static //go:embed frontend/out frontend/out/_next/static
var assets embed.FS var assets embed.FS
type FileLoader struct {
http.Handler
}
func ClientFileLoader() *FileLoader {
return &FileLoader{}
}
func (h *FileLoader) ServeHTTP(res http.ResponseWriter, req *http.Request) {
var err error
requestedFilename := req.URL.Path
fileData, err := os.ReadFile(requestedFilename)
if err != nil {
res.WriteHeader(http.StatusBadRequest)
res.Write([]byte(fmt.Sprintf("Could not load file %s", requestedFilename)))
}
res.Write(fileData)
}
//go:embed build/appicondark.png //go:embed build/appicondark.png
var icon []byte var icon []byte
@ -43,11 +67,14 @@ func main() {
StartHidden: false, StartHidden: false,
HideWindowOnClose: false, HideWindowOnClose: false,
BackgroundColour: &options.RGBA{R: 255, G: 255, B: 255, A: 255}, BackgroundColour: &options.RGBA{R: 255, G: 255, B: 255, A: 255},
Assets: assets, AssetServer: &assetserver.Options{
Menu: nil, Assets: assets,
Logger: nil, Handler: ClientFileLoader(),
LogLevel: logger.DEBUG, },
OnStartup: app.Startup, Menu: nil,
Logger: nil,
LogLevel: logger.DEBUG,
OnStartup: app.Startup,
// OnDomReady: app.domReady, // OnDomReady: app.domReady,
// OnBeforeClose: app.beforeClose, // OnBeforeClose: app.beforeClose,
// OnShutdown: app.shutdown, // OnShutdown: app.shutdown,