send new updates even if we haven't received older ones yet (#16)
* alex/faster: faster * alex/faster: tune throttle
This commit is contained in:
parent
87d7d6114a
commit
d3a515a7f8
|
|
@ -60,7 +60,6 @@ export function LiveImageProvider({
|
||||||
setCount((count) => count + 1)
|
setCount((count) => count + 1)
|
||||||
},
|
},
|
||||||
onResult: (result) => {
|
onResult: (result) => {
|
||||||
console.log(result)
|
|
||||||
if (result.images && result.images[0]) {
|
if (result.images && result.images[0]) {
|
||||||
const id = result.request_id
|
const id = result.request_id
|
||||||
const request = requestsById.get(id)
|
const request = requestsById.get(id)
|
||||||
|
|
@ -90,7 +89,6 @@ export function LiveImageProvider({
|
||||||
},
|
},
|
||||||
timer,
|
timer,
|
||||||
})
|
})
|
||||||
console.log('send', id, req)
|
|
||||||
send({ ...req, request_id: id })
|
send({ ...req, request_id: id })
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
@ -113,33 +111,31 @@ export function LiveImageProvider({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useLiveImage(shapeId: TLShapeId) {
|
export function useLiveImage(
|
||||||
|
shapeId: TLShapeId,
|
||||||
|
{ throttleTime = 64 }: { throttleTime?: number } = {}
|
||||||
|
) {
|
||||||
const editor = useEditor()
|
const editor = useEditor()
|
||||||
const fetchImage = useContext(LiveImageContext)
|
const fetchImage = useContext(LiveImageContext)
|
||||||
if (!fetchImage) throw new Error('Missing LiveImageProvider')
|
if (!fetchImage) throw new Error('Missing LiveImageProvider')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('do effect')
|
|
||||||
let prevHash = ''
|
let prevHash = ''
|
||||||
let prevPrompt = ''
|
let prevPrompt = ''
|
||||||
let prevSvg = ''
|
|
||||||
let state: 'idle' | 'requested-latest' | 'requested-stale' = 'idle'
|
let startedIteration = 0
|
||||||
|
let finishedIteration = 0
|
||||||
|
|
||||||
async function updateDrawing() {
|
async function updateDrawing() {
|
||||||
if (state === 'requested-stale') return
|
|
||||||
if (state === 'requested-latest') {
|
|
||||||
state = 'requested-stale'
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const shapes = getShapesTouching(shapeId, editor)
|
const shapes = getShapesTouching(shapeId, editor)
|
||||||
const frame = editor.getShape<LiveImageShape>(shapeId)!
|
const frame = editor.getShape<LiveImageShape>(shapeId)!
|
||||||
|
|
||||||
const hash = getHashForObject([...shapes])
|
const hash = getHashForObject([...shapes])
|
||||||
if (hash === prevHash && frame.props.name === prevPrompt) return
|
const frameName = frame.props.name
|
||||||
|
if (hash === prevHash && frameName === prevPrompt) return
|
||||||
|
|
||||||
if (state !== 'idle') throw new Error('State should be idle')
|
startedIteration += 1
|
||||||
state = 'requested-latest'
|
const iteration = startedIteration
|
||||||
|
|
||||||
prevHash = hash
|
prevHash = hash
|
||||||
prevPrompt = frame.props.name
|
prevPrompt = frame.props.name
|
||||||
|
|
@ -151,6 +147,8 @@ export function useLiveImage(shapeId: TLShapeId) {
|
||||||
darkMode: editor.user.getIsDarkMode(),
|
darkMode: editor.user.getIsDarkMode(),
|
||||||
bounds: editor.getShapePageBounds(shapeId)!,
|
bounds: editor.getShapePageBounds(shapeId)!,
|
||||||
})
|
})
|
||||||
|
// cancel if stale:
|
||||||
|
if (iteration <= finishedIteration) return
|
||||||
|
|
||||||
if (!svg) {
|
if (!svg) {
|
||||||
console.error('No SVG')
|
console.error('No SVG')
|
||||||
|
|
@ -163,6 +161,8 @@ export function useLiveImage(shapeId: TLShapeId) {
|
||||||
quality: 1,
|
quality: 1,
|
||||||
scale: 512 / frame.props.w,
|
scale: 512 / frame.props.w,
|
||||||
})
|
})
|
||||||
|
// cancel if stale:
|
||||||
|
if (iteration <= finishedIteration) return
|
||||||
|
|
||||||
if (!image) {
|
if (!image) {
|
||||||
console.error('No image')
|
console.error('No image')
|
||||||
|
|
@ -170,18 +170,14 @@ export function useLiveImage(shapeId: TLShapeId) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const prompt = frame.props.name
|
const prompt = frameName
|
||||||
? frame.props.name + ' hd award-winning impressive'
|
? frameName + ' hd award-winning impressive'
|
||||||
: 'A random image that is safe for work and not surprising—something boring like a city or shoe watercolor'
|
: 'A random image that is safe for work and not surprising—something boring like a city or shoe watercolor'
|
||||||
|
|
||||||
const imageDataUri = await blobToDataUri(image)
|
const imageDataUri = await blobToDataUri(image)
|
||||||
|
|
||||||
if (imageDataUri === prevSvg) {
|
// cancel if stale:
|
||||||
console.log('Same image')
|
if (iteration <= finishedIteration) return
|
||||||
return
|
|
||||||
} else {
|
|
||||||
console.log({ imageDataUri, prevSvg })
|
|
||||||
}
|
|
||||||
prevSvg = imageDataUri
|
|
||||||
|
|
||||||
// downloadDataURLAsFile(imageDataUri, 'image.png')
|
// downloadDataURLAsFile(imageDataUri, 'image.png')
|
||||||
|
|
||||||
|
|
@ -195,35 +191,38 @@ export function useLiveImage(shapeId: TLShapeId) {
|
||||||
seed: Math.abs(random() * 10000), // TODO make this configurable in the UI
|
seed: Math.abs(random() * 10000), // TODO make this configurable in the UI
|
||||||
enable_safety_checks: false,
|
enable_safety_checks: false,
|
||||||
})
|
})
|
||||||
|
// cancel if stale:
|
||||||
|
if (iteration <= finishedIteration) return
|
||||||
|
|
||||||
|
finishedIteration = iteration
|
||||||
updateImage(editor, frame.id, result.url)
|
updateImage(editor, frame.id, result.url)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
const isTimeout = e instanceof Error && e.message === 'Timeout'
|
||||||
} finally {
|
if (!isTimeout) {
|
||||||
if (state === 'requested-latest') {
|
console.error(e)
|
||||||
state = 'idle'
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if (state === 'requested-stale') {
|
|
||||||
state = 'idle'
|
// retry if this was the most recent request:
|
||||||
updateDrawing()
|
if (iteration === startedIteration) {
|
||||||
|
requestUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let frame: number | null = null
|
let timer: ReturnType<typeof setTimeout> | null = null
|
||||||
function requestUpdate() {
|
function requestUpdate() {
|
||||||
if (frame) return
|
if (timer !== null) return
|
||||||
frame = requestAnimationFrame(() => {
|
timer = setTimeout(() => {
|
||||||
frame = null
|
timer = null
|
||||||
updateDrawing()
|
updateDrawing()
|
||||||
})
|
}, throttleTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.on('update-drawings' as any, requestUpdate)
|
editor.on('update-drawings' as any, requestUpdate)
|
||||||
return () => {
|
return () => {
|
||||||
editor.off('update-drawings' as any, requestUpdate)
|
editor.off('update-drawings' as any, requestUpdate)
|
||||||
}
|
}
|
||||||
}, [editor, fetchImage, shapeId])
|
}, [editor, fetchImage, shapeId, throttleTime])
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateImage(editor: Editor, shapeId: TLShapeId, url: string | null) {
|
function updateImage(editor: Editor, shapeId: TLShapeId, url: string | null) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue