mirror of
https://github.com/JohnRiceML/clawport-ui.git
synced 2026-08-14 00:47:50 +00:00
- Published as clawport-ui@0.1.0 on npm (unscoped, clawport was taken) - Changed default favicon/sidebar emoji from castle to lobster - Removed "private": true, added npm metadata (description, homepage, repo, keywords, license) - Added prepublishOnly safety gate (tsc + vitest) - Updated README, SETUP, BRANDING docs with npm install instructions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect } from 'react'
|
|
import { useSettings } from '@/app/settings-provider'
|
|
|
|
/**
|
|
* Dynamically sets the browser tab favicon based on the current
|
|
* portal logo settings (uploaded image or emoji).
|
|
*/
|
|
export function DynamicFavicon() {
|
|
const { settings } = useSettings()
|
|
|
|
useEffect(() => {
|
|
const emoji = settings.portalEmoji ?? '\ud83e\udd9e'
|
|
const icon = settings.portalIcon
|
|
const accentColor = settings.accentColor
|
|
const bgHidden = settings.iconBgHidden
|
|
|
|
// Find or create the favicon link element
|
|
let link = document.querySelector<HTMLLinkElement>('link[rel="icon"]')
|
|
if (!link) {
|
|
link = document.createElement('link')
|
|
link.rel = 'icon'
|
|
document.head.appendChild(link)
|
|
}
|
|
|
|
if (icon) {
|
|
// Uploaded image — use directly as favicon
|
|
link.href = icon
|
|
link.type = 'image/jpeg'
|
|
return
|
|
}
|
|
|
|
// Emoji — render to canvas
|
|
const size = 64
|
|
const canvas = document.createElement('canvas')
|
|
canvas.width = size
|
|
canvas.height = size
|
|
const ctx = canvas.getContext('2d')
|
|
if (!ctx) return
|
|
|
|
if (!bgHidden) {
|
|
// Draw colored background circle
|
|
const color = accentColor ?? '#f5c518'
|
|
ctx.fillStyle = color
|
|
ctx.beginPath()
|
|
ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2)
|
|
ctx.fill()
|
|
}
|
|
|
|
// Draw emoji centered
|
|
ctx.textAlign = 'center'
|
|
ctx.textBaseline = 'middle'
|
|
ctx.font = `${bgHidden ? 56 : 40}px serif`
|
|
ctx.fillText(emoji, size / 2, size / 2 + 2)
|
|
|
|
link.href = canvas.toDataURL('image/png')
|
|
link.type = 'image/png'
|
|
}, [settings.portalIcon, settings.portalEmoji, settings.accentColor, settings.iconBgHidden])
|
|
|
|
return null
|
|
}
|