···
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
4
-
import 'package:flutter/services.dart';
5
-
import 'package:provider/provider.dart';
import '../constants/app_colors.dart';
import '../models/post.dart';
9
-
import '../providers/auth_provider.dart';
10
-
import '../providers/vote_provider.dart';
import '../utils/date_time_utils.dart';
12
-
import 'icons/animated_heart_icon.dart';
13
-
import 'icons/reply_icon.dart';
14
-
import 'icons/share_icon.dart';
15
-
import 'sign_in_dialog.dart';
8
+
import 'external_link_bar.dart';
9
+
import 'post_card_actions.dart';
/// Post card widget for displaying feed posts
···
// Community and author info
51
-
// Community avatar placeholder
55
-
decoration: BoxDecoration(
56
-
color: AppColors.primary,
57
-
borderRadius: BorderRadius.circular(4),
61
-
post.post.community.name[0].toUpperCase(),
62
-
style: const TextStyle(
63
-
color: AppColors.textPrimary,
65
-
fontWeight: FontWeight.bold,
46
+
_buildCommunityAvatar(post.post.community),
const SizedBox(width: 8),
···
130
+
// External link (if present)
131
+
if (post.post.embed?.external != null) ...[
132
+
const SizedBox(height: 8),
133
+
ExternalLinkBar(embed: post.post.embed!.external!),
// Reduced spacing before action buttons
const SizedBox(height: 4),
158
-
mainAxisAlignment: MainAxisAlignment.end,
163
-
// TODO: Handle share interaction with backend
165
-
debugPrint('Share button tapped for post');
169
-
// Increased padding for better touch targets
170
-
padding: const EdgeInsets.symmetric(
175
-
color: AppColors.textPrimary.withValues(alpha: 0.6),
179
-
const SizedBox(width: 8),
184
-
// TODO: Navigate to post detail/comments screen
186
-
debugPrint('Comment button tapped for post');
190
-
// Increased padding for better touch targets
191
-
padding: const EdgeInsets.symmetric(
196
-
mainAxisSize: MainAxisSize.min,
199
-
color: AppColors.textPrimary.withValues(alpha: 0.6),
201
-
const SizedBox(width: 5),
203
-
DateTimeUtils.formatCount(
204
-
post.post.stats.commentCount,
207
-
color: AppColors.textPrimary.withValues(alpha: 0.6),
215
-
const SizedBox(width: 8),
218
-
Consumer<VoteProvider>(
219
-
builder: (context, voteProvider, child) {
220
-
final isLiked = voteProvider.isLiked(post.post.uri);
221
-
final adjustedScore = voteProvider.getAdjustedScore(
223
-
post.post.stats.score,
228
-
// Check authentication
229
-
final authProvider = context.read<AuthProvider>();
230
-
if (!authProvider.isAuthenticated) {
231
-
// Show sign-in dialog
232
-
final shouldSignIn = await SignInDialog.show(
234
-
message: 'You need to sign in to like posts.',
140
+
PostCardActions(post: post),
237
-
if ((shouldSignIn ?? false) && context.mounted) {
238
-
// TODO: Navigate to sign-in screen
240
-
debugPrint('Navigate to sign-in screen');
147
+
/// Builds the community avatar widget
148
+
Widget _buildCommunityAvatar(CommunityRef community) {
149
+
if (community.avatar != null && community.avatar!.isNotEmpty) {
150
+
// Show real community avatar
152
+
borderRadius: BorderRadius.circular(4),
153
+
child: CachedNetworkImage(
154
+
imageUrl: community.avatar!,
158
+
placeholder: (context, url) => _buildFallbackAvatar(community),
159
+
errorWidget: (context, url, error) => _buildFallbackAvatar(community),
246
-
// Light haptic feedback on both like and unlike
247
-
await HapticFeedback.lightImpact();
164
+
// Fallback to letter placeholder
165
+
return _buildFallbackAvatar(community);
249
-
// Toggle vote with optimistic update
251
-
await voteProvider.toggleVote(
252
-
postUri: post.post.uri,
253
-
postCid: post.post.cid,
255
-
} on Exception catch (e) {
257
-
debugPrint('Failed to toggle vote: $e');
259
-
// TODO: Show error snackbar
263
-
// Increased padding for better touch targets
264
-
padding: const EdgeInsets.symmetric(
269
-
mainAxisSize: MainAxisSize.min,
273
-
color: AppColors.textPrimary
274
-
.withValues(alpha: 0.6),
275
-
likedColor: const Color(0xFFFF0033),
277
-
const SizedBox(width: 5),
279
-
DateTimeUtils.formatCount(adjustedScore),
281
-
color: AppColors.textPrimary
282
-
.withValues(alpha: 0.6),
168
+
/// Builds a fallback avatar with the first letter of community name
169
+
Widget _buildFallbackAvatar(CommunityRef community) {
173
+
decoration: BoxDecoration(
174
+
color: AppColors.primary,
175
+
borderRadius: BorderRadius.circular(4),
179
+
community.name[0].toUpperCase(),
180
+
style: const TextStyle(
181
+
color: AppColors.textPrimary,
183
+
fontWeight: FontWeight.bold,