diff --git a/lib/src/core/ui/widgets/menu_action_button.dart b/lib/src/core/ui/widgets/menu_action_button.dart index 166770e5..90e6a84f 100644 --- a/lib/src/core/ui/widgets/menu_action_button.dart +++ b/lib/src/core/ui/widgets/menu_action_button.dart @@ -26,15 +26,18 @@ class MenuActionButton extends StatelessWidget { // Check if current user is the author final authRepository = GetIt.instance(); final userDid = authRepository.session?.did; - final isCurrentUserAuthor = userDid == authorDid; + final isCurrentUserAuthor = + userDid != null && authorDid != null && userDid == authorDid; OptionsPanel.show( context: context, - onReport: () { - if (onPressed != null) { - onPressed!(); - } - }, + onReport: isCurrentUserAuthor + ? null + : () { + if (onPressed != null) { + onPressed!(); + } + }, onDelete: isCurrentUserAuthor && onDeletePressed != null ? onDeletePressed : null, diff --git a/lib/src/core/ui/widgets/options_panel.dart b/lib/src/core/ui/widgets/options_panel.dart index 937e14e2..5f2a68f5 100644 --- a/lib/src/core/ui/widgets/options_panel.dart +++ b/lib/src/core/ui/widgets/options_panel.dart @@ -4,7 +4,7 @@ import 'package:spark/src/core/l10n/app_localizations.dart'; class OptionsPanel { static void show({ required BuildContext context, - required VoidCallback onReport, + VoidCallback? onReport, VoidCallback? onDelete, VoidCallback? onBlock, bool isBlocked = false, @@ -55,19 +55,20 @@ class OptionsPanel { onBlock(); }, ), - ListTile( - leading: const Icon(Icons.report_outlined), - title: Text( - isProfile - ? l10n.optionsPanelReportProfile - : l10n.optionsPanelReport, - style: TextStyle(color: textColor), + if (onReport != null) + ListTile( + leading: const Icon(Icons.report_outlined), + title: Text( + isProfile + ? l10n.optionsPanelReportProfile + : l10n.optionsPanelReport, + style: TextStyle(color: textColor), + ), + onTap: () { + Navigator.of(context).pop(); + onReport(); + }, ), - onTap: () { - Navigator.of(context).pop(); - onReport(); - }, - ), ListTile( leading: const Icon(Icons.close), title: Text( diff --git a/lib/src/features/feed/ui/widgets/action_buttons/side_action_bar.dart b/lib/src/features/feed/ui/widgets/action_buttons/side_action_bar.dart index d30145e5..fe05b005 100644 --- a/lib/src/features/feed/ui/widgets/action_buttons/side_action_bar.dart +++ b/lib/src/features/feed/ui/widgets/action_buttons/side_action_bar.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:get_it/get_it.dart'; +import 'package:spark/src/core/auth/data/repositories/auth_repository.dart'; import 'package:spark/src/core/design_system/components/organisms/side_action_bar.dart'; import 'package:spark/src/core/network/atproto/atproto.dart'; import 'package:spark/src/core/routing/app_router.dart'; @@ -15,6 +16,7 @@ import 'package:spark/src/features/feed/providers/feed_provider.dart'; import 'package:spark/src/features/feed/providers/like_post.dart'; import 'package:spark/src/features/feed/providers/repost_post.dart'; import 'package:spark/src/features/feed/ui/widgets/action_buttons/share_panel.dart'; +import 'package:spark/src/features/profile/providers/profile_feed_provider.dart'; class SideActionBar extends ConsumerStatefulWidget { const SideActionBar({ @@ -346,6 +348,63 @@ class SideActionBarState extends ConsumerState { ); } + Future _handleDeletePost() async { + final currentPost = _currentPost ?? widget.post; + final scaffoldMessenger = ScaffoldMessenger.of(context); + final confirmed = await showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('Delete Post'), + content: const Text( + 'Are you sure you want to delete this post? This action cannot be undone.', + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: const Text('Cancel'), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(true), + child: const Text('Delete'), + ), + ], + ), + ); + + if (confirmed != true) return; + + try { + final feedRepository = GetIt.instance().feed; + final success = await feedRepository.deletePost(currentPost.uri); + if (!success) { + throw Exception('Failed to delete post'); + } + + if (widget.feed != null) { + final controller = ref.read( + feedActionControllerProvider(widget.feed!), + ); + controller?.onAdvanceAndRemove(); + } else { + final profileUri = AtUri.parse('at://${currentPost.author.did}'); + ref.invalidate(profileFeedProvider(profileUri, false)); + ref.invalidate(profileFeedProvider(profileUri, true)); + } + + if (mounted) { + scaffoldMessenger.showSnackBar( + const SnackBar(content: Text('Post deleted')), + ); + } + } catch (e) { + if (mounted) { + scaffoldMessenger.showSnackBar( + SnackBar(content: Text('Failed to delete post: $e')), + ); + } + } + } + Future _handleBlock() async { final currentPost = _currentPost ?? widget.post; final author = currentPost.author; @@ -403,6 +462,10 @@ class SideActionBarState extends ConsumerState { // Curation disabled: do not build curate destinations from feeds final currentPost = _currentPost ?? widget.post; + final authRepository = GetIt.instance(); + final userDid = authRepository.session?.did; + final isCurrentUserAuthor = + userDid != null && userDid == currentPost.author.did; final commentCount = currentPost.replyCount ?? int.tryParse(widget.commentCount) ?? 0; @@ -417,8 +480,11 @@ class SideActionBarState extends ConsumerState { onSoundTap: currentPost.sound != null ? _handleSoundTap : null, onOptions: () => OptionsPanel.show( context: context, - onReport: _handleReport, - onBlock: widget.showBlockOption ? _handleBlock : null, + onReport: isCurrentUserAuthor ? null : _handleReport, + onDelete: isCurrentUserAuthor ? _handleDeletePost : null, + onBlock: widget.showBlockOption && !isCurrentUserAuthor + ? _handleBlock + : null, isBlocked: isBlocking(currentPost.author.viewer), ), likeCount: _likeCount.toString(), diff --git a/pubspec.lock b/pubspec.lock index af38ebde..17a7bcfa 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1900,5 +1900,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.9.0 <4.0.0" + dart: ">=3.10.0 <4.0.0" flutter: ">=3.38.0" diff --git a/pubspec.yaml b/pubspec.yaml index ed0989a8..67f82d57 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ publish_to: "none" # The number after + should stay fixed, the android workflow will change it on every build version: 0.5.0+1 environment: - sdk: ^3.8.1 + sdk: ^3.10.0 workspace: - widgetbook - fonts