deriveCoursewarePrefetchUrls function

List<CoursewarePrefetchUrl> deriveCoursewarePrefetchUrls(
  1. List<PlayBackSignalData> signals
)

从回放 metadata 的 signal_data 推导白板实际会加载的课件背景图 URL。

背景:白板真正 fetch 的背景图来自 signal 的 action 201.url(如 .../picture/1.jpg), 与 metadata document_pages 的缩略图(.../thumbnail/1.jpg,且域名不同)不一致, 故不能用缩略图预热。这里直接由 signal_data 还原真实 URL:

  • action 501 建立 fid -> {downloadURL, type} 映射;
  • action 401 的 toBoardId 解析出 (page, fid),对 type==0 文件按 SDK 同款规则拼出 preview URL(paas / cos 两种形式,见 _previewUrlForPage);
  • action 201 的 url 直接采用(与 401 推导结果去重)。

仅返回实际被切换展示过的页(避免把整份文件上百页全部无谓预热);H5 动画 PPT(type==1)跳过。 返回顺序为信令出现顺序(即时间轴顺序),同一 URL 仅保留首次出现。

Implementation

List<CoursewarePrefetchUrl> deriveCoursewarePrefetchUrls(
  List<PlayBackSignalData> signals,
) {
  final files = <String, _FileInfo>{};
  final result = <CoursewarePrefetchUrl>[];
  final seen = <String>{};

  void addUrl(int offsetMs, String url) {
    if (url.isEmpty) return;
    if (seen.add(url)) result.add(CoursewarePrefetchUrl(offsetMs, url));
  }

  for (final s in signals) {
    final dynamic decoded;
    try {
      decoded = jsonDecode(s.value);
    } catch (_) {
      continue;
    }
    if (decoded is! Map) continue;
    final actions = decoded['actions'];
    if (actions is! List) continue;

    for (final a in actions) {
      if (a is! Map) continue;
      final action = a['action'];

      if (action == _kActionAddFile) {
        final file = a['file'];
        if (file is Map) {
          final fid = file['fid']?.toString();
          final downloadURL = file['downloadURL']?.toString() ?? '';
          final type = _asInt(file['type'], -1);
          if (fid != null && fid.isNotEmpty) {
            files[fid] = _FileInfo(downloadURL: downloadURL, type: type);
          }
        }
      } else if (action == _kActionUpdateBgImg) {
        // type 缺省按图片处理;H5/其它显式类型跳过。
        final type = a['type'];
        final url = a['url']?.toString() ?? '';
        if ((type == null || _asInt(type, -1) == _kTranscodeTypeStaticImage) &&
            url.isNotEmpty) {
          addUrl(s.offset, url);
        }
      } else if (action == _kActionSwitch) {
        final toBoardId = a['toBoardId']?.toString() ?? '';
        final derived = _bgUrlFromBoardId(toBoardId, files);
        if (derived != null) addUrl(s.offset, derived);
      }
    }
  }

  return result;
}