From a7d4975e182d38641f987df2d291be2182874cf4 Mon Sep 17 00:00:00 2001
From: LittleSheep <littlesheep.code@hotmail.com>
Date: Sat, 26 Apr 2025 17:55:32 +0800
Subject: [PATCH] :sparkles: Post editing

---
 lib/screens/posts/compose.dart  | 16 ++++---
 lib/widgets/post/post_item.dart | 76 +++++++++++++++++++++------------
 2 files changed, 60 insertions(+), 32 deletions(-)

diff --git a/lib/screens/posts/compose.dart b/lib/screens/posts/compose.dart
index 96ff36a..7ac71b4 100644
--- a/lib/screens/posts/compose.dart
+++ b/lib/screens/posts/compose.dart
@@ -185,8 +185,8 @@ class PostComposeScreen extends HookConsumerWidget {
         );
 
         final client = ref.watch(apiClientProvider);
-        await client.post(
-          '/posts',
+        await client.request(
+          originalPost == null ? '/posts' : '/posts/${originalPost!.id}',
           data: {
             'content': contentController.text,
             'attachments':
@@ -195,7 +195,10 @@ class PostComposeScreen extends HookConsumerWidget {
                     .map((e) => e.data.id)
                     .toList(),
           },
-          options: Options(headers: {'X-Pub': currentPublisher.value?.name}),
+          options: Options(
+            headers: {'X-Pub': currentPublisher.value?.name},
+            method: originalPost == null ? 'POST' : 'PATCH',
+          ),
         );
         if (context.mounted) {
           context.maybePop(true);
@@ -223,6 +226,8 @@ class PostComposeScreen extends HookConsumerWidget {
                         strokeWidth: 2.5,
                       ),
                     ).center()
+                    : originalPost != null
+                    ? const Icon(LucideIcons.edit)
                     : const Icon(LucideIcons.upload),
           ),
           const Gap(8),
@@ -357,7 +362,8 @@ class _AttachmentPreview extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return AspectRatio(
-      aspectRatio: 1,
+      aspectRatio:
+          (item.isOnCloud ? (item.data.fileMeta?['ratio'] ?? 1) : 1).toDouble(),
       child: ClipRRect(
         borderRadius: BorderRadius.circular(8),
         child: Stack(
@@ -485,7 +491,7 @@ class _AttachmentPreview extends StatelessWidget {
                       color: Colors.black.withOpacity(0.5),
                       padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                       child:
-                          (item is SnCloudFile)
+                          (item.isOnCloud)
                               ? Row(
                                 mainAxisSize: MainAxisSize.min,
                                 children: [
diff --git a/lib/widgets/post/post_item.dart b/lib/widgets/post/post_item.dart
index d9a1212..e14d1fd 100644
--- a/lib/widgets/post/post_item.dart
+++ b/lib/widgets/post/post_item.dart
@@ -1,10 +1,12 @@
 import 'package:auto_route/auto_route.dart';
+import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:island/models/post.dart';
 import 'package:island/route.gr.dart';
 import 'package:island/widgets/content/cloud_file_collection.dart';
 import 'package:island/widgets/content/cloud_files.dart';
 import 'package:island/widgets/content/markdown.dart';
+import 'package:lucide_icons/lucide_icons.dart';
 import 'package:styled_widget/styled_widget.dart';
 
 class PostItem extends StatelessWidget {
@@ -23,39 +25,59 @@ class PostItem extends StatelessWidget {
     final renderingPadding =
         padding ?? EdgeInsets.symmetric(horizontal: 12, vertical: 16);
 
-    return Padding(
-      padding: renderingPadding,
-      child: Column(
-        spacing: 8,
-        children: [
-          Row(
-            crossAxisAlignment: CrossAxisAlignment.start,
-            spacing: 12,
-            children: [
-              ProfilePictureWidget(item: item.publisher.picture),
-              Expanded(
-                child: GestureDetector(
-                  child: Column(
+    return CupertinoContextMenu.builder(
+      actions: [
+        CupertinoContextMenuAction(
+          trailingIcon: LucideIcons.edit,
+          onPressed: () {
+            context.router.push(PostEditRoute(id: item.id));
+          },
+          child: Text('Edit'),
+        ),
+      ],
+      builder: (context, animation) {
+        return Material(
+          color: Theme.of(context).colorScheme.surface,
+          child: SingleChildScrollView(
+            physics: const NeverScrollableScrollPhysics(),
+            child: Padding(
+              padding: renderingPadding,
+              child: Column(
+                spacing: 8,
+                children: [
+                  Row(
+                    mainAxisSize: MainAxisSize.min,
                     crossAxisAlignment: CrossAxisAlignment.start,
+                    spacing: 12,
                     children: [
-                      Text(item.publisher.nick).bold(),
-                      if (item.content.isNotEmpty)
-                        MarkdownTextContent(content: item.content),
+                      ProfilePictureWidget(item: item.publisher.picture),
+                      Expanded(
+                        child: GestureDetector(
+                          child: Column(
+                            crossAxisAlignment: CrossAxisAlignment.start,
+                            children: [
+                              Text(item.publisher.nick).bold(),
+                              if (item.content.isNotEmpty)
+                                MarkdownTextContent(content: item.content),
+                            ],
+                          ),
+                          onTap: () {
+                            if (isOpenable) {
+                              context.router.push(PostDetailRoute(id: item.id));
+                            }
+                          },
+                        ),
+                      ),
                     ],
                   ),
-                  onTap: () {
-                    if (isOpenable) {
-                      context.router.push(PostDetailRoute(id: item.id));
-                    }
-                  },
-                ),
+                  if (item.attachments.isNotEmpty)
+                    CloudFileList(files: item.attachments),
+                ],
               ),
-            ],
+            ),
           ),
-          if (item.attachments.isNotEmpty)
-            CloudFileList(files: item.attachments),
-        ],
-      ),
+        );
+      },
     );
   }
 }