用户自建应用图标方案

技术方案 + 效果演示

问题

目前用户创建应用时通过 emoji 指定图标,直接渲染原生 emoji 文本。问题是各平台 emoji 渲染差异很大,尤其 Windows 上比较丑,缺乏品牌感。

方案

渐变圆角背景 + Twemoji SVG,用户选两样东西:一个 emoji + 一个背景色。

效果演示

技术实现要点

1. Twemoji SVG CDN

使用 jdecked/twemoji(Twitter Twemoji 的社区维护 fork,持续更新)。

URL 格式是纯算的,不需要映射表、不需要安装依赖

https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/svg/{codepoints}.svg

转换函数:

function emojiToTwemojiUrl(emoji: string): string {
  const codepoints = [...emoji]
    .map(c => c.codePointAt(0)!.toString(16))
    .filter(cp => cp !== 'fe0f')  // 去掉变体选择符
    .join('-');
  return `https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/svg/${codepoints}.svg`;
}

// 例:emojiToTwemojiUrl('☀️') → ".../2600.svg"
// 例:emojiToTwemojiUrl('🤖') → ".../1f916.svg"

2. 渐变色板

预设 12 个低饱和度渐变,用户从中选一个作为背景。存储只存色板 index 或渐变值字符串。

3. 渲染结构

<!-- 最终渲染的 DOM 结构 -->
<span style="
  width: 64px; height: 64px;
  border-radius: 16px;            /* size * 0.25 */
  background: linear-gradient(135deg, #7db8d4, #5a9bb8);
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
">
  <img
    src="https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/svg/2600.svg"
    width="36" height="36"
    onerror="回退到原生 emoji 文本"
  />
</span>

4. 数据模型

现有 IconSource 类型已支持 { text: string },建议扩展为:

// 新增一种 icon 类型,或者复用 text 并新增 background 字段
type IconSource =
  | { builtin: string }
  | { url: string }
  | { text: string }
  | { emoji: string; background: string }   // 新增

emoji 存原始 emoji 字符(如 "☀️"),background 存渐变 CSS 值。

5. 回退策略

6. 离线场景

盒子部署可能断网。两个选择:

涉及的改动点

位置改动
blade-os / AppIcon.tsxrenderIconContent 里新增 emoji 类型分支,渲染 Twemoji img + 渐变背景
blade-os / os-sdkIconSource 类型扩展,加 { emoji, background }
应用创建/编辑 UI新增 emoji picker + 色板选择器
后端 apps.yamlicon 字段支持新格式