From a691be07fa582d5135eac7a1cf192bc739e13735 Mon Sep 17 00:00:00 2001 From: Ponshu Developer Date: Mon, 6 Apr 2026 09:12:59 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20simplify=20list=20item=20=E2=80=94=20ac?= =?UTF-8?q?curate=20info=20only,=20remove=20AI-inferred=20tags?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 酒蔵 · 都道府県: / → · 区切りに変更(詳細画面と統一) - フレーバータグ削除: AI推測精度が低いため一覧から除去(詳細画面のみ) - 特定名称 + アルコール度数を追加: ラベル直読みの正確な情報のみ表示 (どちらか一方のみの場合も対応、両方ない場合は行自体を非表示) - セット商品の説明文は維持(ユーザー入力のため) - お気に入りアイコンは現状(右上)のまま維持 Co-Authored-By: Claude Sonnet 4.6 --- lib/widgets/home/sake_list_item.dart | 70 ++++++++++++++++------------ 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/lib/widgets/home/sake_list_item.dart b/lib/widgets/home/sake_list_item.dart index 636d53f..195f75c 100644 --- a/lib/widgets/home/sake_list_item.dart +++ b/lib/widgets/home/sake_list_item.dart @@ -161,49 +161,34 @@ class SakeListItem extends ConsumerWidget { const Icon(Icons.favorite, color: Colors.pink, size: 16), ], ), - const SizedBox(height: AppTheme.spacingTiny), - // Brand / Prefecture (セット商品では非表示) + const SizedBox(height: 3), + // 酒蔵 · 都道府県(セット商品では非表示) if (sake.itemType != ItemType.set && (sake.displayData.displayBrewery.isNotEmpty || sake.displayData.displayPrefecture.isNotEmpty)) - Row( - children: [ - Expanded( - child: Text( - '${sake.displayData.displayBrewery} / ${sake.displayData.displayPrefecture}', - style: Theme.of(context).textTheme.bodySmall, - overflow: TextOverflow.ellipsis, - ), - ), - ], + Text( + '${sake.displayData.displayBrewery} · ${sake.displayData.displayPrefecture}', + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: appColors.textSecondary, + ), + overflow: TextOverflow.ellipsis, + maxLines: 1, ), - // セット商品の説明文表示 + // セット商品の説明文(ユーザー入力のため維持) if (sake.itemType == ItemType.set && sake.displayData.catchCopy != null) Text( sake.displayData.catchCopy!, style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: appColors.textSecondary, fontStyle: FontStyle.italic, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), - if (!isMenuMode && sake.hiddenSpecs.flavorTags.isNotEmpty) ...[ - const SizedBox(height: AppTheme.spacingSmall), - Wrap( - spacing: 4, - runSpacing: 4, - children: sake.hiddenSpecs.flavorTags.take(3).map((tag) => Container( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - decoration: BoxDecoration( - color: appColors.surfaceSubtle, - borderRadius: BorderRadius.circular(4), - ), - child: Text( - tag, - style: TextStyle(fontSize: 10, color: appColors.textSecondary), - ), - )).toList(), - ) - ] + // 特定名称 + アルコール度数(ラベルから直接読んだ正確な情報) + if (!isMenuMode && sake.itemType != ItemType.set) ...[ + const SizedBox(height: 6), + _buildSpecLine(context, appColors), + ], ], ), ), @@ -214,4 +199,27 @@ class SakeListItem extends ConsumerWidget { ), // Card ); // Pressable } + + /// 特定名称 + アルコール度数(どちらもある場合は両方、片方のみも対応) + Widget _buildSpecLine(BuildContext context, AppColors appColors) { + final type = sake.hiddenSpecs.type; + final alcohol = sake.hiddenSpecs.alcoholContent; + + final parts = []; + if (type != null && type.isNotEmpty) parts.add(type); + if (alcohol != null) parts.add('${alcohol.toStringAsFixed(alcohol.truncateToDouble() == alcohol ? 0 : 1)}%'); + + if (parts.isEmpty) return const SizedBox.shrink(); + + return Text( + parts.join(' · '), + style: TextStyle( + fontSize: 11, + color: appColors.textSecondary, + fontWeight: FontWeight.w500, + ), + overflow: TextOverflow.ellipsis, + maxLines: 1, + ); + } }