feat: share radars via self-contained URL links

The app has no backend, so a share link embeds the whole radar as
base64url in the query string. Opening /share?d=... validates and
imports a fresh copy into the recipient's radars, then opens it.
This commit is contained in:
Julien Calixte
2026-06-19 15:43:43 +02:00
parent 3f9dd514ce
commit a371f11811
5 changed files with 181 additions and 1 deletions

View File

@@ -7,6 +7,7 @@ import CriteriaEditor from "../components/CriteriaEditor.vue"
import ProfilesEditor from "../components/ProfilesEditor.vue"
import ScoreGrid from "../components/ScoreGrid.vue"
import { svgToPngBlob, downloadBlob, copyBlobToClipboard, slugify } from "../utils/png"
import { encodeRadar } from "../utils/share"
const props = defineProps<{ id: string }>()
const router = useRouter()
@@ -59,6 +60,18 @@ async function downloadPng(): Promise<void> {
}
}
async function copyShareLink(): Promise<void> {
if (!radar.value) return
const href = router.resolve({ name: "share", query: { d: encodeRadar(radar.value) } }).href
try {
await navigator.clipboard.writeText(`${location.origin}${href}`)
flash("success", "Share link copied")
} catch (err) {
console.error(err)
flash("error", "Could not copy link")
}
}
async function copyPng(): Promise<void> {
const svg = getSvg()
if (!svg) return
@@ -99,6 +112,7 @@ async function copyPng(): Promise<void> {
/>
</div>
<div class="flex gap-2 mt-1">
<button class="btn btn-outline" @click="copyShareLink">Share link</button>
<button class="btn btn-outline" @click="copyPng">Copy PNG</button>
<button class="btn btn-primary" @click="downloadPng">Download PNG</button>
</div>