jim800121chen 50a3f73acd feat(local-tool): 品牌視覺設計 + 內建模型首次啟動 seed
#8 首次啟動 seed 內建模型:
- app.go 新增 seedUserDataDir() 在 server spawn 之前執行
- 若 user data-dir 缺 models.json,從 locateBundleDataDir() 複製
  models.json + nef/ 預置模型過去
- 新增 locateBundleDataDir() / copyFile() / copyDirRecursive() helper
- user 第一次開 app 會看到 8 個 Kneron 預置 .nef 模型(kl520×5 + kl720×3)

#5 #6 #7 品牌視覺:
- 新增 branding/ 目錄存放設計資產與生成工具
  - logo.svg(向量原始稿)
  - icon-{16,...,1024}.png(10 種尺寸)
  - icon.ico(Windows 多解析度 ICO,PNG-in-ICO 格式)
  - icon.icns(macOS)
  - tools/gen_icon.go + gen_ico.go(純 Go 生成工具,未來調整 logo 用)
  - README.md + 色票表
- 部署:
  - visiona-local/build/appicon.png → Wails build 會嵌入 exe
  - visiona-local/frontend/icon.png → splash 使用
  - frontend/src/app/favicon.ico + icon.png → Next.js App Router favicon
- splash page 升級:加 logo icon + 品牌名 visionA Local + tagline Edge AI Workspace
- Wails window title: "visionA Local — Edge AI Workspace"
- wails.json productName: "visionA Local"
- Next.js metadata title + icons
- i18n: en/zh-TW 把殘留的 "Edge AI 平台" 字串改為 visionA Local 品牌
- .iss: SetupIconFile 指向 branding/icon.ico + UninstallDisplayIcon +
  ArchitecturesAllowed 改 x64compatible 修掉之前的 deprecation warning

品牌色票:
- 主色 #4F7EFF(電子藍)
- 輔色 #6EF3C5(mint 點綴)
- 深色背景漸層 #1A1F36 → #0E1222
- 警示 #FF6B6B

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 04:42:41 +08:00

96 lines
2.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 把多張 PNG 打包成 Windows .icoPNG-in-ICO 格式Vista+ 支援)
// 用法go run gen_ico.go <output.ico> <png-dir> <sizes-csv>
// 範例go run gen_ico.go icon.ico ../ 16,24,32,48,64,96,128,256
//go:build ignore
package main
import (
"bytes"
"encoding/binary"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
)
type iconDir struct {
Reserved uint16
Type uint16
Count uint16
}
type iconDirEntry struct {
Width uint8
Height uint8
ColorCount uint8
Reserved uint8
Planes uint16
BitCount uint16
SizeBytes uint32
Offset uint32
}
func main() {
if len(os.Args) < 4 {
fmt.Fprintln(os.Stderr, "usage: gen_ico <output.ico> <png-dir> <sizes-csv>")
os.Exit(1)
}
outPath := os.Args[1]
pngDir := os.Args[2]
sizesCSV := os.Args[3]
var sizes []int
for _, s := range strings.Split(sizesCSV, ",") {
n, err := strconv.Atoi(strings.TrimSpace(s))
if err != nil {
fmt.Fprintln(os.Stderr, "bad size:", s)
os.Exit(1)
}
sizes = append(sizes, n)
}
pngs := make([][]byte, len(sizes))
for i, s := range sizes {
data, err := os.ReadFile(filepath.Join(pngDir, "icon-"+strconv.Itoa(s)+".png"))
if err != nil {
fmt.Fprintln(os.Stderr, "read", s, err)
os.Exit(1)
}
pngs[i] = data
}
var buf bytes.Buffer
binary.Write(&buf, binary.LittleEndian, iconDir{Reserved: 0, Type: 1, Count: uint16(len(sizes))})
headerSize := 6 + 16*len(sizes)
offset := uint32(headerSize)
for i, s := range sizes {
w := uint8(s)
h := uint8(s)
if s >= 256 {
w = 0
h = 0
}
entry := iconDirEntry{
Width: w,
Height: h,
Planes: 1,
BitCount: 32,
SizeBytes: uint32(len(pngs[i])),
Offset: offset,
}
binary.Write(&buf, binary.LittleEndian, entry)
offset += uint32(len(pngs[i]))
}
for _, p := range pngs {
buf.Write(p)
}
if err := os.WriteFile(outPath, buf.Bytes(), 0644); err != nil {
fmt.Fprintln(os.Stderr, "write", err)
os.Exit(1)
}
fmt.Println("wrote", outPath, "containing", len(sizes), "images")
}