Skip to content

Commit

Permalink
implemented showOpenFileDialog fn and fixed base64 write temp file an…
Browse files Browse the repository at this point in the history
…d general code formatting
  • Loading branch information
meganoahj authored and Simon-Laux committed Oct 17, 2024
1 parent ebed056 commit 99e73be
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 17 deletions.
4 changes: 3 additions & 1 deletion packages/frontend/src/components/composer/Composer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,9 @@ const Composer = forwardRef<

try {
// Write clipboard to file then attach it to the draft
const path = await runtime.writeClipboardToTempFile(file.name || `file.${extension(file.type)}`)
const path = await runtime.writeClipboardToTempFile(
file.name || `file.${extension(file.type)}`
)
await addFileToDraft(path, msgType)
// delete file again after it was sucessfuly added
await runtime.removeTempFile(path)
Expand Down
4 changes: 4 additions & 0 deletions packages/target-browser/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,7 @@ pnpm run start
Then point your browser to <https://localhost:3000> and acept the locally signed certificate to continue.

> If you get an "The connection was reset"-Error, then you have likely forgotten to use http**s** instead of http.
### Known broken things

> Image Cropper is broken because accesing tmp files directly isn't implemented. Suggestion: handle image preview in cache or memory.
75 changes: 62 additions & 13 deletions packages/target-browser/runtime-browser/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ class BrowserRuntime implements Runtime {
const clipboardItems = await navigator.clipboard.read()
for (const clipboardItem of clipboardItems) {
for (const type of clipboardItem.types) {
if (type === 'text/html') { /* ignores html. Needed for images copied from web */
if (type === 'text/html') {
/* ignores html. Needed for images copied from web */
continue
}
const blob = await clipboardItem.getType(type)
Expand All @@ -296,14 +297,34 @@ class BrowserRuntime implements Runtime {
}
throw new Error('No supported clipboard item found')
}
writeTempFileFromBase64(_name: string, _content: string): Promise<string> {
throw new Error('Method not implemented.')
}
writeTempFile(_name: string, _content: string): Promise<string> {
throw new Error('Method not implemented.')
async writeTempFileFromBase64(
name: string,
content: string
): Promise<string> {
return (
await (
await fetch(`/backend-api/uploadTempFileB64/${name}`, {
method: 'POST',
body: content,
})
).json()
).path
}
async writeTempFile(name: string, content: string): Promise<string> {
return (
await (
await fetch(`/backend-api/uploadTempFile/${name}`, {
method: 'POST',
body: content,
})
).json()
).path
}
removeTempFile(_name: string): Promise<void> {
throw new Error('Method not implemented.')
async removeTempFile(name: string): Promise<void> {
await fetch(`/backend-api/removeTempFile`, {
method: 'POST',
body: name,
})
}

activeNotifications: { [chatId: number]: Notification[] } = {}
Expand Down Expand Up @@ -520,7 +541,7 @@ class BrowserRuntime implements Runtime {
}
if (blob.type !== 'image/png') {
const img = new Image()
const blobPromise = new Promise<Blob>((resolve, reject) => {
const blobPromise = new Promise<Blob>(async (resolve, reject) => {

Check failure on line 544 in packages/target-browser/runtime-browser/runtime.ts

View workflow job for this annotation

GitHub Actions / Code Validation

Promise executor functions should not be async
img.onload = async () => {
try {
const canvas = new OffscreenCanvas(
Expand Down Expand Up @@ -569,10 +590,38 @@ class BrowserRuntime implements Runtime {
}
return ''
}
async showOpenFileDialog(
_options: RuntimeOpenDialogOptions
): Promise<string> {
throw new Error('Method not implemented.')
async showOpenFileDialog(options: RuntimeOpenDialogOptions): Promise<string> {
const extstring = options.filters
?.map(filter => filter.extensions)
.reduce((p, c) => c.concat(p))
.map(ext => `.${ext}`)
.join()
return new Promise(resolve => {
const input = document.createElement('input')
input.type = 'file'
input.accept = extstring || ''
input.onchange = async () => {
if (input.files != null) {
resolve(
(
await (
await fetch(
`/backend-api/uploadTempFile/${input.files[0].name}`,
{
method: 'POST',
body: input.files[0],
}
)
).json()
).path
)
} else {
resolve('')
}
}

input.click()
})
}

openLink(link: string): void {
Expand Down
56 changes: 53 additions & 3 deletions packages/target-browser/src/backendApi.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import express, { json as BodyParserJson, Router } from 'express'
import { mkdtemp, writeFile } from 'fs/promises'
import { mkdtemp, writeFile, unlink } from 'fs/promises'
import { basename, join } from 'path'
import { tmpdir } from 'os'
import {
Expand Down Expand Up @@ -64,7 +64,7 @@ BackendApiRoute.post(
type: () => {
return true /* Accept all filetypes */
},
limit: '500mb'
limit: '500mb',
}),
async (req, res) => {
try {
Expand All @@ -80,7 +80,57 @@ BackendApiRoute.post(
console.log(tmpFile)
console.log(filename, tmppath, filepath)
} catch (error) {
res.status(500).json({message: 'Failed to create Tempfile'})
res.status(500).json({ message: 'Failed to create Tempfile' })
}
}
)

BackendApiRoute.post(
'/uploadTempFileB64/:filename',
express.raw({
type: () => {
return true /* Accept all filetypes */
},
limit: '500mb',
}),
async (req, res) => {
try {
const tmpFilebin: Buffer = Buffer.from(req.body.toString(), 'base64')

const filename = basename(req.params.filename)
const tmppath = await mkdtemp(join(tmpdir(), 'tmp-'))

const filepath = join(tmppath, filename)
await writeFile(filepath, tmpFilebin, 'binary')

res.status(200).send({ path: filepath })
console.log(tmpFilebin.toString('utf-8'))
console.log(filename, tmppath, filepath)
} catch (error) {
res.status(500).json({ message: 'Failed to create Tempfile' })
}
}
)

BackendApiRoute.post(
'/removeTempFile',
express.raw({
type: () => {
return true /* Accept all filetypes */
},
}),
async (req, _res) => {
try {
const filepath = req.body.toString('utf8')
console.log(filepath)
if (filepath.includes('tmp') && !filepath.includes('..')) {
await unlink(filepath)
}
} catch (e) {
// file doesn't exist, no permissions, etc..
// full list of possible errors is here
// http://man7.org/linux/man-pages/man2/unlink.2.html#ERRORS
console.log(e)
}
}
)

0 comments on commit 99e73be

Please sign in to comment.