mobile bluesky app made with flutter
lazurite.stormlightlabs.org/
mobile
bluesky
flutter
1import 'package:bluesky/app_bsky_graph_defs.dart' as bsky_graph;
2import 'package:flutter/material.dart';
3import 'package:lazurite/core/theme/theme_extensions.dart';
4import 'package:lazurite/shared/presentation/widgets/profile_avatar.dart';
5
6/// A reusable tile for a single [bsky_graph.ListView] entry.
7class ListRowTile extends StatelessWidget {
8 const ListRowTile({super.key, required this.list, this.onTap, this.trailing});
9
10 final bsky_graph.ListView list;
11 final VoidCallback? onTap;
12 final Widget? trailing;
13
14 @override
15 Widget build(BuildContext context) {
16 final colorScheme = context.colorScheme;
17 final isMod = list.purpose.knownValue == bsky_graph.KnownListPurpose.appBskyGraphDefsModlist;
18 final purposeLabel = isMod ? 'MOD' : 'FEED';
19 final purposeColor = isMod ? colorScheme.error : colorScheme.primary;
20
21 return ListTile(
22 key: key,
23 leading: ProfileAvatar(
24 size: 40,
25 imageUrl: list.avatar,
26 fallbackText: list.name,
27 fallbackBuilder: (_) => Icon(Icons.list, color: colorScheme.onSurfaceVariant),
28 ),
29 title: Text(list.name, maxLines: 1, overflow: TextOverflow.ellipsis),
30 subtitle: Text('${list.listItemCount ?? 0} members', style: TextStyle(color: colorScheme.onSurfaceVariant)),
31 trailing:
32 trailing ??
33 Container(
34 padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
35 decoration: BoxDecoration(
36 color: purposeColor.withValues(alpha: 0.1),
37 borderRadius: BorderRadius.circular(4),
38 border: Border.all(color: purposeColor.withValues(alpha: 0.3)),
39 ),
40 child: Text(
41 purposeLabel,
42 style: TextStyle(fontSize: 11, fontWeight: FontWeight.w700, color: purposeColor, letterSpacing: 1),
43 ),
44 ),
45 onTap: onTap,
46 );
47 }
48}