Improve Save for browsers without File System Access API

- Save As prompts for filename via prompt() before downloading
- Save reuses the filename from last Save As (no repeated prompts)
- Banner in Safari/Firefox explaining the limitation with Chrome link
- Banner is dismissible
This commit is contained in:
Danila Poyarkov 2026-03-01 15:41:27 +03:00
parent c886daded2
commit c8af1c35e7
4 changed files with 35 additions and 1 deletions

1
components.d.ts vendored
View file

@ -84,6 +84,7 @@ declare module 'vue' {
PagesPanel: typeof import('./src/components/PagesPanel.vue')['default']
PositionSection: typeof import('./src/components/properties/PositionSection.vue')['default']
PropertiesPanel: typeof import('./src/components/PropertiesPanel.vue')['default']
SafariBanner: typeof import('./src/components/SafariBanner.vue')['default']
ScrubInput: typeof import('./src/components/ScrubInput.vue')['default']
StrokeSection: typeof import('./src/components/properties/StrokeSection.vue')['default']
Toolbar: typeof import('./src/components/Toolbar.vue')['default']

View file

@ -10,6 +10,7 @@ import { provideEditorStore } from './stores/editor'
import EditorCanvas from './components/EditorCanvas.vue'
import LayersPanel from './components/LayersPanel.vue'
import PropertiesPanel from './components/PropertiesPanel.vue'
import SafariBanner from './components/SafariBanner.vue'
import Toolbar from './components/Toolbar.vue'
const store = provideEditorStore()
@ -35,6 +36,7 @@ if (!('test' in params)) {
<template>
<div class="flex h-screen w-screen flex-col">
<SafariBanner />
<SplitterGroup
v-if="showChrome"
direction="horizontal"

View file

@ -0,0 +1,25 @@
<script setup lang="ts">
import { ref } from 'vue'
import { IS_TAURI } from '@/constants'
const dismissed = ref(false)
const show = !IS_TAURI && typeof window !== 'undefined' && !window.showSaveFilePicker
</script>
<template>
<div
v-if="show && !dismissed"
class="flex items-center gap-2 border-b border-amber-500/30 bg-amber-500/10 px-3 py-1.5 text-xs text-amber-200"
>
<span class="flex-1">
Your browser doesn't support the local file API. Files will be downloaded instead of saved in place.
<a href="https://www.google.com/chrome/" target="_blank" class="underline">Use Chrome</a> or Edge for full support.
</span>
<button
class="shrink-0 rounded px-1.5 py-0.5 text-amber-300 transition-colors hover:bg-amber-500/20"
@click="dismissed = true"
>
Dismiss
</button>
</div>
</template>

View file

@ -117,6 +117,7 @@ export function createEditorStore() {
const pageViewports = new Map<string, PageViewport>()
let fileHandle: FileSystemFileHandle | null = null
let filePath: string | null = null
let downloadName: string | null = null
let savedVersion = 0
let autosaveTimer: ReturnType<typeof setTimeout> | undefined
let _ck: import('canvaskit-wasm').CanvasKit | null = null
@ -586,6 +587,8 @@ export function createEditorStore() {
async function saveFigFile() {
if (filePath || fileHandle) {
await writeFile(await buildFigFile())
} else if (downloadName) {
downloadBlob(new Uint8Array(await buildFigFile()), downloadName, 'application/octet-stream')
} else {
await saveFigFileAs()
}
@ -627,7 +630,10 @@ export function createEditorStore() {
}
}
downloadBlob(new Uint8Array(data), 'Untitled.fig', 'application/octet-stream')
const filename = prompt('Save as:', downloadName ?? 'Untitled.fig')
if (!filename) return
downloadName = filename
downloadBlob(new Uint8Array(data), filename, 'application/octet-stream')
}
async function writeFile(data: Uint8Array) {