65 lines
1.9 KiB
TypeScript
65 lines
1.9 KiB
TypeScript
import type { ViewportSize } from '@/app/document/io/types'
|
|
|
|
export function resolveBrowserFileURL(path: string): URL {
|
|
const url = new URL(path, window.location.href)
|
|
url.hash = ''
|
|
return url
|
|
}
|
|
|
|
export function yieldToUI(): Promise<void> {
|
|
return new Promise((resolve) => {
|
|
requestAnimationFrame(() => resolve())
|
|
})
|
|
}
|
|
|
|
type ViewportEditor = {
|
|
zoomToFit: () => void
|
|
}
|
|
|
|
export function createDocumentViewportActions(editor: ViewportEditor, viewportSize: ViewportSize) {
|
|
function setViewportSize(width: number, height: number) {
|
|
viewportSize.width = width
|
|
viewportSize.height = height
|
|
}
|
|
|
|
async function fitCurrentPageToViewport() {
|
|
await yieldToUI()
|
|
editor.zoomToFit()
|
|
}
|
|
|
|
return { setViewportSize, fitCurrentPageToViewport }
|
|
}
|
|
|
|
// The File System Access pickers (showSaveFilePicker/showOpenFilePicker) and
|
|
// window.prompt are blocked by browsers inside cross-origin sub-frames
|
|
// (Chrome: "Cross origin sub frames aren't allowed to show a file picker").
|
|
// Detect that context so callers can fall back to a plain download / file
|
|
// input instead of surfacing the picker error.
|
|
export function isCrossOriginSubFrame(): boolean {
|
|
const top = window.top
|
|
if (!top || top === window) return false
|
|
try {
|
|
// Same-origin sub-frame: the top window is reachable and pickers are allowed.
|
|
void top.location.href
|
|
return false
|
|
} catch {
|
|
// Cross-origin sub-frame: top navigation is blocked, pickers are not allowed.
|
|
return true
|
|
}
|
|
}
|
|
|
|
export function downloadBlob(data: Uint8Array, filename: string, mime: string) {
|
|
const blob = new Blob([data.buffer as ArrayBuffer], { type: mime })
|
|
const url = URL.createObjectURL(blob)
|
|
const a = document.createElement('a')
|
|
a.href = url
|
|
a.download = filename
|
|
a.style.display = 'none'
|
|
document.body.appendChild(a)
|
|
a.click()
|
|
setTimeout(() => {
|
|
document.body.removeChild(a)
|
|
URL.revokeObjectURL(url)
|
|
}, 100)
|
|
}
|