Skip to content

feat(files): 统一文件夹自定义图标与 connector 图标展示契约 #556

Description

@AptS-1547

背景

AsterDrive 当前文件夹展示使用固定的 FolderGlyph / Folder 图标。存储 connector descriptor 已经有 connector-owned 的 icon_src / icon_name,但目前只用于管理员存储策略选择卡片;文件夹列表接口也没有返回目录的策略或展示元数据。

后续需要支持:

  1. 用户为文件夹设置自己选择的图标。
  2. 文件夹显式绑定某个存储策略时,可以显示该策略对应 connector 的图标,帮助用户识别目录的存储落点。
  3. 文件夹自定义图标与 connector 图标可以同时存在,不互相覆盖。

推荐业务契约

展示优先级

  • 文件夹自定义图标:主图标。
  • 没有自定义图标、但文件夹存在显式 storage policy override:使用该 connector 图标作为主图标。
  • 没有以上信息:使用默认 FolderGlyph。
  • 自定义图标存在时,connector 图标作为右下角小徽标和 tooltip 保留,不替换用户选择。

第一期只把“显式绑定在当前文件夹上的 policy”作为 connector 展示来源。用户默认 policy、团队 policy group、祖先目录继承策略不直接伪装成当前文件夹属性;如未来需要展示 effective policy,单独增加 source: explicit | inherited | default 的存储信息语义。

后端统一返回展示语义

不要让前端拿 policy_id 再查询 policy、按 driver_type 拼图标。由后端在目录服务层解析并返回稳定的展示 DTO,例如:

FolderPresentation
  primary: default | custom | connector
  custom_icon: preset | uploaded
  connector_badge: connector_id + stable icon reference

该 DTO 需要复用到 FolderListItemFolderInfoFolderAncestorItem,并覆盖个人空间、团队空间、搜索、分享视图和目录树。公共分享默认只暴露自定义图标,不暴露 connector/storage 细节。

Connector 图标

现有 descriptor 的图标能力应提升为稳定的 connector-owned asset contract:

  • 内置 connector 可以继续使用同源静态资源。
  • connector/plugin 通过 manifest 自带图标时,由服务端提供版本化、同源、可缓存的资源地址。
  • 保留安全的 core icon-name fallback;不允许前端维护 driver 白名单,也不把任意远程 URL 当作事实源。
  • 不把图标 URL 持久化到 storage policy;policy 只保存稳定 connector_id。
  • 资源缺失、connector 不可用或 descriptor 不完整时,统一回退默认图标。

文件夹自定义图标

自定义图标属于文件夹展示元数据,不应作为普通用户文件写入当前 storage policy:

  • 建议使用独立的 folder icon asset 记录/媒体命名空间,避免被文件配额、策略迁移、文件列表和 blob 清理语义影响。
  • 上传图标先限制为 PNG/JPEG/WebP,服务端校验尺寸和解码预算,统一转换为小尺寸 WebP 并移除元数据;首期不接受任意 SVG。
  • 对外只返回稳定的同源资源地址和版本/ETag,不返回数据库路径或任意用户 URL。
  • 设置/清除需要文件夹管理权限;读取沿用文件夹可见性。
  • rename/move/restore 保留图标;copy 按产品语义复制图标;purge 清理资产;设置、替换、清除写审计并触发 storage change refresh。

建议拆分

子项 A:connector-owned icon contract

  • StorageConnectorUiDescriptor 的图标字段收口为结构化、版本化的图标描述。
  • 统一管理员策略页和文件夹展示的 connector 图标渲染入口。
  • 补同源资源、icon-name fallback、缺失资源和缓存行为测试。
  • 为未来 connector/plugin manifest 自带图标保留服务端资源边界,但不在本项引入任意插件 UI。

子项 B:custom folder icon and unified folder presentation

  • 增加文件夹图标元数据/资产 migration、repository、权限校验和设置/清除 API。
  • 增加 FolderPresentation,由后端一次解析自定义图标、显式 policy connector 和默认图标。
  • 同步 REST/OpenAPI/前端生成类型,覆盖列表、详情、面包屑、目录树、搜索、分享和回收站需要的展示面。
  • FolderGridItemFolderNameCellFolderTreeItemContent 等入口改为统一图标渲染器。
  • 覆盖 custom > connector > default 优先级、copy/move/trash/restore/purge、公共分享脱敏、connector 缺失回退和缓存刷新。

明确不做

  • 不在前端新增 driver_type / connector_id 白名单矩阵。
  • 不让文件夹图标直接引用任意外部 URL。
  • 不把自定义图标当普通文件计入当前目录 storage policy。
  • 不在本 issue 内实现完整 storage-driver plugin runtime。

验收标准

  • 同一个文件夹在列表、网格、树、搜索和分享视图中的图标语义一致。
  • 设置/清除自定义图标后,所有相关视图能通过现有刷新机制收敛。
  • 显式 policy connector 变化后,connector 图标随 descriptor 事实源更新,不需要前端改矩阵。
  • 不泄漏 connector 凭据、配置或不必要的存储拓扑信息。
  • OpenAPI、SQLite 测试、权限/失败回滚、前端 focused tests 和公共分享边界均有证据。

当前调查依据

  • src/services/files/folder/models.rsFolderListItem 当前没有 policy 或 presentation 字段。
  • src/services/workspace/models.rsFolderInfo 只有显式 policy_id
  • crates/aster_drive_storage/src/connector_descriptor.rs:已有 connector-owned icon_src / icon_name
  • src/services/workspace/storage_core/policy.rs:effective policy 还涉及祖先和个人/团队 policy group,不能由前端猜测。
  • frontend-panel/src/components/files/FolderGlyph.tsxFolderGridItem.tsxFileTableCells.tsxFolderTreeItemContent.tsx:当前展示入口分散,需要统一 renderer。

这是设计和拆分跟踪 issue;实现前按上述契约补齐子 issue 和最终 API 形态。

Metadata

Metadata

Labels

CI: RunningA pull request has required CI workflows that have not reached a terminal stateEnhancementNew feature or requestPriority: LowLow priority issueScope: FilesCore file and folder product behaviorScope: StorageStorage policies, connectors, drivers, provider capabilities, and storage backendsStatus: Needs DecisionA product, evidence, or design decision is required before implementation commitmentTracking: EpicParent or tracking issue whose completion is represented by linked sub-issues or phasesTypeScriptPull requests that update JavaScript code

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions