Files
patbond-flutter/lib/features/community/community_display.dart
T
lixi 8aac8c52cc
CI / flutter-gates (push) Successful in 2m41s
新增:首页 Feed 接入真实数据——四态/尾部三态/聚合曝光埋点,社区 demo 消亡第一页(T3-14)
- home_page Feed segment 改接 CommunityController:骨架屏首载、空态 CTA、
  错误横幅重试、下拉刷新(失败保留旧列表 + SnackBar)、触底游标翻页
  (失败态只走显式重试,不随滚动风暴自动重打)
- PostCard 三形态(单图通栏 4:3 / 多图折叠封面 +N 角标 / 纯文字 6 行)+
  PostMediaGrid(列数规则 + ink 80% scrim 精算)+ LikeButton(error 族修订
  Colors.red,T3-14 纯展示禁用态,ToggleSync 接线留 T3-15/16)+ FeedSkeleton
  (呼吸动效尊重减弱动态设置);降级作者统一「宠友」占位
- SignedNetworkImage:预签名 URL 缓存 key 剥离 X-Amz-* 签名参数,
  RemoteImage 全仓换用(同图不同签名命中同一缓存条目)
- feed 域埋点:feed_viewed 聚合曝光(浏览段开/结算于切 Tab、切分段、
  退后台、销毁;≥50% 可见 ≥500ms 段内按帖去重,postId 不上报)+
  feed_load_failed(refresh/load_more 双路,会话失效不报)
- integration_test/feed_live_test.dart:compose 六容器 Linux 桌面真链路
  实测入口(PATBOND_FEED_LIVE=1 门控,默认跳过)
- 测试 379 → 421(+42):四态/尾部三态/翻页不丢不重/降级作者/曝光结算
  时机/缓存 key/事件属性全覆盖;analyze 0,format 无 diff

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 13:01:43 +08:00

34 lines
1.7 KiB
Dart

import 'package:patbond_flutter/core/network/api_exception.dart';
import 'package:patbond_flutter/features/community/community_models.dart';
/// 降级作者([AuthorSummary.isDegraded],资料暂不可得或已注销)的
/// 统一占位名(05 号规范:占位头像 + 默认名,客户端不做昵称回退拼装)。
const degradedAuthorName = '宠友';
/// 作者展示名:正常路径 nickname 恒非空(服务端已回退 username);
/// 降级形态统一 [degradedAuthorName]。
String authorDisplayName(AuthorSummary author) =>
author.nickname ?? degradedAuthorName;
/// Feed 卡片元信息的相对时间(正典「2 小时前」语言)。
/// [now] 注入口供测试锁定时钟。
String feedRelativeTime(DateTime time, {DateTime? now}) {
final reference = now ?? DateTime.now();
final difference = reference.difference(time.toLocal());
if (difference.inMinutes < 1) return '刚刚';
if (difference.inHours < 1) return '${difference.inMinutes} 分钟前';
if (difference.inDays < 1) return '${difference.inHours} 小时前';
if (difference.inDays < 7) return '${difference.inDays} 天前';
final local = time.toLocal();
if (local.year == reference.year) return '${local.month}${local.day}日';
return '${local.year}${local.month}${local.day}日';
}
/// Feed 加载失败的用户话术(pets 域 petLoadErrorMessage 同构;
/// 服务端原始 message 不上屏)。
String feedLoadErrorMessage(ApiException? error) => switch (error) {
ApiNetworkException _ => '网络异常,请检查网络后重试',
ApiRateLimitException _ => '请求过于频繁,请稍后再试',
_ => '动态加载失败,请稍后重试',
};