Compare commits
	
		
			2 Commits
		
	
	
		
			8bc8556f06
			...
			01da729365
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 01da729365 | |||
| cef313b356 | 
@@ -48,6 +48,28 @@
 | 
				
			|||||||
  "deletePublisherHint": "Are you sure to delete this publisher? This will also deleted all the post and collections under this publisher.",
 | 
					  "deletePublisherHint": "Are you sure to delete this publisher? This will also deleted all the post and collections under this publisher.",
 | 
				
			||||||
  "somethingWentWrong": "Something went wrong...",
 | 
					  "somethingWentWrong": "Something went wrong...",
 | 
				
			||||||
  "deletePost": "Delete Post",
 | 
					  "deletePost": "Delete Post",
 | 
				
			||||||
 | 
					  "safetyReport": "Report",
 | 
				
			||||||
 | 
					  "safetyReportTitle": "Safety Report",
 | 
				
			||||||
 | 
					  "safetyReportDescription": "Help us keep the community safe by reporting inappropriate content or behavior.",
 | 
				
			||||||
 | 
					  "safetyReportType": "Report Type",
 | 
				
			||||||
 | 
					  "safetyReportReason": "Additional Details",
 | 
				
			||||||
 | 
					  "safetyReportReasonHint": "Please provide more details about the issue...",
 | 
				
			||||||
 | 
					  "safetyReportSubmit": "Submit Report",
 | 
				
			||||||
 | 
					  "safetyReportSubmitting": "Submitting...",
 | 
				
			||||||
 | 
					  "safetyReportSuccess": "Report submitted successfully. Thank you for helping keep our community safe.",
 | 
				
			||||||
 | 
					  "safetyReportError": "Failed to submit report. Please try again.",
 | 
				
			||||||
 | 
					  "safetyReportReasonRequired": "Please provide details about the issue",
 | 
				
			||||||
 | 
					  "safetyReportTypeSpam": "Spam or Misleading",
 | 
				
			||||||
 | 
					  "safetyReportTypeHarassment": "Harassment or Abuse",
 | 
				
			||||||
 | 
					  "safetyReportTypeHateSpeech": "Hate Speech",
 | 
				
			||||||
 | 
					  "safetyReportTypeViolence": "Violence or Threats",
 | 
				
			||||||
 | 
					  "safetyReportTypeAdultContent": "Adult Content",
 | 
				
			||||||
 | 
					  "safetyReportTypeIntellectualProperty": "Intellectual Property Violation",
 | 
				
			||||||
 | 
					  "safetyReportTypeOther": "Other",
 | 
				
			||||||
 | 
					  "safetyReportTypeInappropriate": "Inappropriate Content",
 | 
				
			||||||
 | 
					  "safetyReportTypeCopyright": "Copyright Violation",
 | 
				
			||||||
 | 
					  "safetyReportSuccessTitle": "Report Submitted",
 | 
				
			||||||
 | 
					  "safetyReportErrorTitle": "Error",
 | 
				
			||||||
  "deletePostHint": "Are you sure to delete this post?",
 | 
					  "deletePostHint": "Are you sure to delete this post?",
 | 
				
			||||||
  "copyLink": "Copy Link",
 | 
					  "copyLink": "Copy Link",
 | 
				
			||||||
  "postCreateAccountTitle": "Thanks for joining!",
 | 
					  "postCreateAccountTitle": "Thanks for joining!",
 | 
				
			||||||
@@ -566,5 +588,27 @@
 | 
				
			|||||||
  "uploadingFiles": "Uploading files...",
 | 
					  "uploadingFiles": "Uploading files...",
 | 
				
			||||||
  "sharedSuccessfully": "Shared successfully!",
 | 
					  "sharedSuccessfully": "Shared successfully!",
 | 
				
			||||||
  "navigateToChat": "Navigate to Chat",
 | 
					  "navigateToChat": "Navigate to Chat",
 | 
				
			||||||
  "wouldYouLikeToNavigateToChat": "Would you like to navigate to the chat?"
 | 
					  "wouldYouLikeToNavigateToChat": "Would you like to navigate to the chat?",
 | 
				
			||||||
 | 
					  "abuseReport": "Report",
 | 
				
			||||||
 | 
					  "abuseReportTitle": "Report Content",
 | 
				
			||||||
 | 
					  "abuseReportDescription": "Help us keep the community safe by reporting inappropriate content or behavior.",
 | 
				
			||||||
 | 
					  "abuseReportType": "Report Type",
 | 
				
			||||||
 | 
					  "abuseReportReason": "Additional Details",
 | 
				
			||||||
 | 
					  "abuseReportReasonHint": "Please provide more details about the issue...",
 | 
				
			||||||
 | 
					  "abuseReportSubmit": "Submit Report",
 | 
				
			||||||
 | 
					  "abuseReportSuccess": "Report submitted successfully. Thank you for helping keep our community safe.",
 | 
				
			||||||
 | 
					  "abuseReportError": "Failed to submit report. Please try again.",
 | 
				
			||||||
 | 
					  "abuseReportReasonRequired": "Please provide details about the issue",
 | 
				
			||||||
 | 
					  "abuseReportSuccessTitle": "Report Submitted",
 | 
				
			||||||
 | 
					  "abuseReportErrorTitle": "Error",
 | 
				
			||||||
 | 
					  "abuseReportTypeSpam": "Spam or Misleading",
 | 
				
			||||||
 | 
					  "abuseReportTypeHarassment": "Harassment or Abuse",
 | 
				
			||||||
 | 
					  "abuseReportTypeInappropriate": "Inappropriate Content",
 | 
				
			||||||
 | 
					  "abuseReportTypeViolence": "Violence or Threats",
 | 
				
			||||||
 | 
					  "abuseReportTypeCopyright": "Copyright Violation",
 | 
				
			||||||
 | 
					  "abuseReportTypeImpersonation": "Impersonation",
 | 
				
			||||||
 | 
					  "abuseReportTypeOffensiveContent": "Offensive Content",
 | 
				
			||||||
 | 
					  "abuseReportTypePrivacyViolation": "Privacy Violation",
 | 
				
			||||||
 | 
					  "abuseReportTypeIllegalContent": "Illegal Content",
 | 
				
			||||||
 | 
					  "abuseReportTypeOther": "Other"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			|||||||
import 'dart:math' as math;
 | 
					import 'dart:math' as math;
 | 
				
			||||||
import 'package:island/models/embed.dart';
 | 
					import 'package:island/models/embed.dart';
 | 
				
			||||||
import 'package:island/models/post.dart';
 | 
					import 'package:island/models/post.dart';
 | 
				
			||||||
 | 
					import 'package:island/pods/config.dart';
 | 
				
			||||||
import 'package:island/pods/network.dart';
 | 
					import 'package:island/pods/network.dart';
 | 
				
			||||||
import 'package:island/pods/userinfo.dart';
 | 
					import 'package:island/pods/userinfo.dart';
 | 
				
			||||||
import 'package:island/route.gr.dart';
 | 
					import 'package:island/route.gr.dart';
 | 
				
			||||||
@@ -20,6 +21,7 @@ import 'package:island/widgets/content/cloud_file_collection.dart';
 | 
				
			|||||||
import 'package:island/widgets/content/cloud_files.dart';
 | 
					import 'package:island/widgets/content/cloud_files.dart';
 | 
				
			||||||
import 'package:island/widgets/content/embed/link.dart';
 | 
					import 'package:island/widgets/content/embed/link.dart';
 | 
				
			||||||
import 'package:island/widgets/content/markdown.dart';
 | 
					import 'package:island/widgets/content/markdown.dart';
 | 
				
			||||||
 | 
					import 'package:island/widgets/safety/abuse_report_helper.dart';
 | 
				
			||||||
import 'package:island/widgets/post/post_replies_sheet.dart';
 | 
					import 'package:island/widgets/post/post_replies_sheet.dart';
 | 
				
			||||||
import 'package:island/widgets/share/share_sheet.dart';
 | 
					import 'package:island/widgets/share/share_sheet.dart';
 | 
				
			||||||
import 'package:material_symbols_icons/symbols.dart';
 | 
					import 'package:material_symbols_icons/symbols.dart';
 | 
				
			||||||
@@ -125,18 +127,29 @@ class PostItem extends HookConsumerWidget {
 | 
				
			|||||||
                context.router.push(PostComposeRoute(forwardedPost: item));
 | 
					                context.router.push(PostComposeRoute(forwardedPost: item));
 | 
				
			||||||
              },
 | 
					              },
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 | 
					            MenuSeparator(),
 | 
				
			||||||
            MenuAction(
 | 
					            MenuAction(
 | 
				
			||||||
              title: 'share'.tr(),
 | 
					              title: 'share'.tr(),
 | 
				
			||||||
              image: MenuImage.icon(Symbols.share),
 | 
					              image: MenuImage.icon(Symbols.share),
 | 
				
			||||||
              callback: () {
 | 
					              callback: () {
 | 
				
			||||||
                showShareSheetLink(
 | 
					                showShareSheetLink(
 | 
				
			||||||
                  context: context,
 | 
					                  context: context,
 | 
				
			||||||
                  link: 'https://solsynth.dev/posts/${item.id}',
 | 
					                  link: '${ref.read(serverUrlProvider)}/posts/${item.id}',
 | 
				
			||||||
                  title: 'sharePost'.tr(),
 | 
					                  title: 'sharePost'.tr(),
 | 
				
			||||||
                  toSystem: true,
 | 
					                  toSystem: true,
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
              },
 | 
					              },
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 | 
					            MenuAction(
 | 
				
			||||||
 | 
					              title: 'abuseReport'.tr(),
 | 
				
			||||||
 | 
					              image: MenuImage.icon(Symbols.flag),
 | 
				
			||||||
 | 
					              callback: () {
 | 
				
			||||||
 | 
					                showAbuseReportSheet(
 | 
				
			||||||
 | 
					                  context,
 | 
				
			||||||
 | 
					                  resourceIdentifier: 'posts:${item.id}',
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
          ],
 | 
					          ],
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								lib/widgets/safety/abuse_report_helper.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								lib/widgets/safety/abuse_report_helper.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:island/widgets/safety/abuse_report_sheet.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Helper function to show the safety report sheet
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// [context] - The build context
 | 
				
			||||||
 | 
					/// [resourceIdentifier] - The identifier of the resource being reported (e.g., post ID, user ID, etc.)
 | 
				
			||||||
 | 
					/// [initialReason] - Optional initial reason text to pre-fill the form
 | 
				
			||||||
 | 
					Future<void> showAbuseReportSheet(
 | 
				
			||||||
 | 
					  BuildContext context, {
 | 
				
			||||||
 | 
					  required String resourceIdentifier,
 | 
				
			||||||
 | 
					  String? initialReason,
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
					  return showModalBottomSheet<void>(
 | 
				
			||||||
 | 
					    context: context,
 | 
				
			||||||
 | 
					    isScrollControlled: true,
 | 
				
			||||||
 | 
					    useRootNavigator: true,
 | 
				
			||||||
 | 
					    builder:
 | 
				
			||||||
 | 
					        (context) => AbuseReportSheet(
 | 
				
			||||||
 | 
					          resourceIdentifier: resourceIdentifier,
 | 
				
			||||||
 | 
					          initialReason: initialReason,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										184
									
								
								lib/widgets/safety/abuse_report_sheet.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								lib/widgets/safety/abuse_report_sheet.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,184 @@
 | 
				
			|||||||
 | 
					import 'package:easy_localization/easy_localization.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_hooks/flutter_hooks.dart';
 | 
				
			||||||
 | 
					import 'package:gap/gap.dart';
 | 
				
			||||||
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
 | 
					import 'package:island/pods/network.dart';
 | 
				
			||||||
 | 
					import 'package:island/widgets/alert.dart';
 | 
				
			||||||
 | 
					import 'package:island/widgets/content/sheet.dart';
 | 
				
			||||||
 | 
					import 'package:material_symbols_icons/symbols.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AbuseReportSheet extends HookConsumerWidget {
 | 
				
			||||||
 | 
					  final String resourceIdentifier;
 | 
				
			||||||
 | 
					  final String? initialReason;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const AbuseReportSheet({
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					    required this.resourceIdentifier,
 | 
				
			||||||
 | 
					    this.initialReason,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context, WidgetRef ref) {
 | 
				
			||||||
 | 
					    final reasonController = useTextEditingController(
 | 
				
			||||||
 | 
					      text: initialReason ?? '',
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    final selectedType = useState<int>(0);
 | 
				
			||||||
 | 
					    final isSubmitting = useState<bool>(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final reportTypes = [
 | 
				
			||||||
 | 
					      {'value': 0, 'label': 'abuseReportTypeCopyright'.tr()},
 | 
				
			||||||
 | 
					      {'value': 1, 'label': 'abuseReportTypeHarassment'.tr()},
 | 
				
			||||||
 | 
					      {'value': 2, 'label': 'abuseReportTypeImpersonation'.tr()},
 | 
				
			||||||
 | 
					      {'value': 3, 'label': 'abuseReportTypeOffensiveContent'.tr()},
 | 
				
			||||||
 | 
					      {'value': 4, 'label': 'abuseReportTypeSpam'.tr()},
 | 
				
			||||||
 | 
					      {'value': 5, 'label': 'abuseReportTypePrivacyViolation'.tr()},
 | 
				
			||||||
 | 
					      {'value': 6, 'label': 'abuseReportTypeIllegalContent'.tr()},
 | 
				
			||||||
 | 
					      {'value': 7, 'label': 'abuseReportTypeOther'.tr()},
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Future<void> submitReport() async {
 | 
				
			||||||
 | 
					      isSubmitting.value = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        final client = ref.read(apiClientProvider);
 | 
				
			||||||
 | 
					        await client.post(
 | 
				
			||||||
 | 
					          '/safety/reports',
 | 
				
			||||||
 | 
					          data: {
 | 
				
			||||||
 | 
					            'resource_identifier': resourceIdentifier,
 | 
				
			||||||
 | 
					            'type': selectedType.value,
 | 
				
			||||||
 | 
					            'reason': reasonController.text.trim(),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (context.mounted) {
 | 
				
			||||||
 | 
					          Navigator.of(context).pop();
 | 
				
			||||||
 | 
					          showDialog(
 | 
				
			||||||
 | 
					            context: context,
 | 
				
			||||||
 | 
					            builder:
 | 
				
			||||||
 | 
					                (contextDialog) => AlertDialog(
 | 
				
			||||||
 | 
					                  icon: const Icon(
 | 
				
			||||||
 | 
					                    Icons.check_circle,
 | 
				
			||||||
 | 
					                    color: Colors.green,
 | 
				
			||||||
 | 
					                    size: 36,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  title: Text('abuseReportSuccessTitle'.tr()),
 | 
				
			||||||
 | 
					                  content: Text('abuseReportSuccess'.tr()),
 | 
				
			||||||
 | 
					                  actions: [
 | 
				
			||||||
 | 
					                    TextButton(
 | 
				
			||||||
 | 
					                      onPressed: () {
 | 
				
			||||||
 | 
					                        Navigator.of(contextDialog).pop();
 | 
				
			||||||
 | 
					                        Navigator.of(context).pop();
 | 
				
			||||||
 | 
					                      },
 | 
				
			||||||
 | 
					                      child: const Text('OK'),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ],
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } catch (err) {
 | 
				
			||||||
 | 
					        showErrorAlert(err);
 | 
				
			||||||
 | 
					      } finally {
 | 
				
			||||||
 | 
					        isSubmitting.value = false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return SheetScaffold(
 | 
				
			||||||
 | 
					      titleText: 'abuseReportTitle'.tr(),
 | 
				
			||||||
 | 
					      child: SingleChildScrollView(
 | 
				
			||||||
 | 
					        padding: EdgeInsets.all(16),
 | 
				
			||||||
 | 
					        child: Column(
 | 
				
			||||||
 | 
					          crossAxisAlignment: CrossAxisAlignment.start,
 | 
				
			||||||
 | 
					          children: [
 | 
				
			||||||
 | 
					            // Information text
 | 
				
			||||||
 | 
					            Container(
 | 
				
			||||||
 | 
					              padding: const EdgeInsets.all(12),
 | 
				
			||||||
 | 
					              decoration: BoxDecoration(
 | 
				
			||||||
 | 
					                color: Theme.of(context).colorScheme.surfaceVariant,
 | 
				
			||||||
 | 
					                borderRadius: BorderRadius.circular(8),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              child: Row(
 | 
				
			||||||
 | 
					                children: [
 | 
				
			||||||
 | 
					                  Icon(
 | 
				
			||||||
 | 
					                    Symbols.info,
 | 
				
			||||||
 | 
					                    size: 20,
 | 
				
			||||||
 | 
					                    color: Theme.of(context).colorScheme.onSurfaceVariant,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  const Gap(8),
 | 
				
			||||||
 | 
					                  Expanded(
 | 
				
			||||||
 | 
					                    child: Text(
 | 
				
			||||||
 | 
					                      'abuseReportDescription'.tr(),
 | 
				
			||||||
 | 
					                      style: Theme.of(context).textTheme.bodySmall?.copyWith(
 | 
				
			||||||
 | 
					                        color: Theme.of(context).colorScheme.onSurfaceVariant,
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            const Gap(24),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Report type selection
 | 
				
			||||||
 | 
					            Text(
 | 
				
			||||||
 | 
					              'abuseReportType'.tr(),
 | 
				
			||||||
 | 
					              style: Theme.of(
 | 
				
			||||||
 | 
					                context,
 | 
				
			||||||
 | 
					              ).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            const Gap(12),
 | 
				
			||||||
 | 
					            ...reportTypes.map((type) {
 | 
				
			||||||
 | 
					              return RadioListTile<int>(
 | 
				
			||||||
 | 
					                value: type['value'] as int,
 | 
				
			||||||
 | 
					                groupValue: selectedType.value,
 | 
				
			||||||
 | 
					                onChanged: (value) => selectedType.value = value!,
 | 
				
			||||||
 | 
					                title: Text(type['label'] as String),
 | 
				
			||||||
 | 
					                contentPadding: EdgeInsets.zero,
 | 
				
			||||||
 | 
					                visualDensity: VisualDensity.compact,
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					            const Gap(24),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Reason text field
 | 
				
			||||||
 | 
					            Text(
 | 
				
			||||||
 | 
					              'abuseReportReason'.tr(),
 | 
				
			||||||
 | 
					              style: Theme.of(
 | 
				
			||||||
 | 
					                context,
 | 
				
			||||||
 | 
					              ).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            const Gap(8),
 | 
				
			||||||
 | 
					            TextField(
 | 
				
			||||||
 | 
					              controller: reasonController,
 | 
				
			||||||
 | 
					              maxLines: 4,
 | 
				
			||||||
 | 
					              decoration: InputDecoration(
 | 
				
			||||||
 | 
					                hintText: 'abuseReportReasonHint'.tr(),
 | 
				
			||||||
 | 
					                border: OutlineInputBorder(
 | 
				
			||||||
 | 
					                  borderRadius: BorderRadius.circular(8),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                filled: true,
 | 
				
			||||||
 | 
					                fillColor: Theme.of(context).colorScheme.surface,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            const Gap(24),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Submit button
 | 
				
			||||||
 | 
					            SizedBox(
 | 
				
			||||||
 | 
					              width: double.infinity,
 | 
				
			||||||
 | 
					              child: FilledButton(
 | 
				
			||||||
 | 
					                onPressed: isSubmitting.value ? null : submitReport,
 | 
				
			||||||
 | 
					                child:
 | 
				
			||||||
 | 
					                    isSubmitting.value
 | 
				
			||||||
 | 
					                        ? const SizedBox(
 | 
				
			||||||
 | 
					                          height: 20,
 | 
				
			||||||
 | 
					                          width: 20,
 | 
				
			||||||
 | 
					                          child: CircularProgressIndicator(strokeWidth: 2),
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                        : Text('abuseReportSubmit'.tr()),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            const Gap(16),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -133,14 +133,6 @@ class _ShareSheetState extends ConsumerState<ShareSheet> {
 | 
				
			|||||||
    super.dispose();
 | 
					    super.dispose();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void _handleClose() {
 | 
					 | 
				
			||||||
    if (widget.onClose != null) {
 | 
					 | 
				
			||||||
      widget.onClose!();
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      Navigator.of(context).pop();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Future<void> _shareToPost() async {
 | 
					  Future<void> _shareToPost() async {
 | 
				
			||||||
    setState(() => _isLoading = true);
 | 
					    setState(() => _isLoading = true);
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
@@ -813,63 +805,6 @@ class _CompactShareOption extends StatelessWidget {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _ShareOption extends StatelessWidget {
 | 
					 | 
				
			||||||
  final IconData icon;
 | 
					 | 
				
			||||||
  final String title;
 | 
					 | 
				
			||||||
  final String subtitle;
 | 
					 | 
				
			||||||
  final VoidCallback? onTap;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const _ShareOption({
 | 
					 | 
				
			||||||
    required this.icon,
 | 
					 | 
				
			||||||
    required this.title,
 | 
					 | 
				
			||||||
    required this.subtitle,
 | 
					 | 
				
			||||||
    this.onTap,
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override
 | 
					 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					 | 
				
			||||||
    return Card(
 | 
					 | 
				
			||||||
      margin: EdgeInsets.zero,
 | 
					 | 
				
			||||||
      child: ListTile(
 | 
					 | 
				
			||||||
        leading: Icon(
 | 
					 | 
				
			||||||
          icon,
 | 
					 | 
				
			||||||
          color:
 | 
					 | 
				
			||||||
              onTap != null
 | 
					 | 
				
			||||||
                  ? Theme.of(context).colorScheme.primary
 | 
					 | 
				
			||||||
                  : Theme.of(
 | 
					 | 
				
			||||||
                    context,
 | 
					 | 
				
			||||||
                  ).colorScheme.onSurfaceVariant.withOpacity(0.5),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        title: Text(
 | 
					 | 
				
			||||||
          title,
 | 
					 | 
				
			||||||
          style: TextStyle(
 | 
					 | 
				
			||||||
            color:
 | 
					 | 
				
			||||||
                onTap != null
 | 
					 | 
				
			||||||
                    ? null
 | 
					 | 
				
			||||||
                    : Theme.of(
 | 
					 | 
				
			||||||
                      context,
 | 
					 | 
				
			||||||
                    ).colorScheme.onSurfaceVariant.withOpacity(0.5),
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        subtitle: Text(
 | 
					 | 
				
			||||||
          subtitle,
 | 
					 | 
				
			||||||
          style: TextStyle(
 | 
					 | 
				
			||||||
            color:
 | 
					 | 
				
			||||||
                onTap != null
 | 
					 | 
				
			||||||
                    ? Theme.of(context).colorScheme.onSurfaceVariant
 | 
					 | 
				
			||||||
                    : Theme.of(
 | 
					 | 
				
			||||||
                      context,
 | 
					 | 
				
			||||||
                    ).colorScheme.onSurfaceVariant.withOpacity(0.5),
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        trailing: onTap != null ? const Icon(Symbols.chevron_right) : null,
 | 
					 | 
				
			||||||
        onTap: onTap,
 | 
					 | 
				
			||||||
        enabled: onTap != null,
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class _ContentPreview extends StatelessWidget {
 | 
					class _ContentPreview extends StatelessWidget {
 | 
				
			||||||
  final ShareContent content;
 | 
					  final ShareContent content;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user