From e9ef0c887afe9afdbd6f5c63ee00c28304b1b0bd Mon Sep 17 00:00:00 2001
From: Daniel Supernault
Date: Mon, 26 Jul 2021 22:49:46 -0600
Subject: [PATCH] Add Archive Posts
---
.../Controllers/Api/BaseApiController.php | 75 ++++++-
.../assets/js/components/PostComponent.vue | 25 +++
resources/assets/js/components/Profile.vue | 200 ++++++++++++------
.../js/components/partials/ContextMenu.vue | 35 ++-
.../js/components/partials/StatusCard.vue | 11 +-
.../views/site/help/sharing-media.blade.php | 77 +++++--
routes/web.php | 3 +
7 files changed, 346 insertions(+), 80 deletions(-)
diff --git a/app/Http/Controllers/Api/BaseApiController.php b/app/Http/Controllers/Api/BaseApiController.php
index 0e62013f4..70401eba5 100644
--- a/app/Http/Controllers/Api/BaseApiController.php
+++ b/app/Http/Controllers/Api/BaseApiController.php
@@ -15,7 +15,8 @@ use App\{
Media,
Notification,
Profile,
- Status
+ Status,
+ StatusArchived
};
use App\Transformer\Api\{
AccountTransformer,
@@ -39,6 +40,7 @@ use App\Jobs\VideoPipeline\{
use App\Services\NotificationService;
use App\Services\MediaPathService;
use App\Services\MediaBlocklistService;
+use App\Services\StatusService;
class BaseApiController extends Controller
{
@@ -286,4 +288,75 @@ class BaseApiController extends Controller
return response()->json($res, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
}
+
+ public function archive(Request $request, $id)
+ {
+ abort_if(!$request->user(), 403);
+
+ $status = Status::whereNull('in_reply_to_id')
+ ->whereNull('reblog_of_id')
+ ->whereProfileId($request->user()->profile_id)
+ ->findOrFail($id);
+
+ if($status->scope === 'archived') {
+ return [200];
+ }
+
+ $archive = new StatusArchived;
+ $archive->status_id = $status->id;
+ $archive->profile_id = $status->profile_id;
+ $archive->original_scope = $status->scope;
+ $archive->save();
+
+ $status->scope = 'archived';
+ $status->visibility = 'draft';
+ $status->save();
+
+ StatusService::del($status->id);
+
+ // invalidate caches
+
+ return [200];
+ }
+
+ public function unarchive(Request $request, $id)
+ {
+ abort_if(!$request->user(), 403);
+
+ $status = Status::whereNull('in_reply_to_id')
+ ->whereNull('reblog_of_id')
+ ->whereProfileId($request->user()->profile_id)
+ ->findOrFail($id);
+
+ if($status->scope !== 'archived') {
+ return [200];
+ }
+
+ $archive = StatusArchived::whereStatusId($status->id)
+ ->whereProfileId($status->profile_id)
+ ->firstOrFail();
+
+ $status->scope = $archive->original_scope;
+ $status->visibility = $archive->original_scope;
+ $status->save();
+
+ $archive->delete();
+
+ return [200];
+ }
+
+ public function archivedPosts(Request $request)
+ {
+ abort_if(!$request->user(), 403);
+
+ $statuses = Status::whereProfileId($request->user()->profile_id)
+ ->whereScope('archived')
+ ->orderByDesc('id')
+ ->simplePaginate(10);
+
+ $fractal = new Fractal\Manager();
+ $fractal->setSerializer(new ArraySerializer());
+ $resource = new Fractal\Resource\Collection($statuses, new StatusStatelessTransformer());
+ return $fractal->createData($resource)->toArray();
+ }
}
diff --git a/resources/assets/js/components/PostComponent.vue b/resources/assets/js/components/PostComponent.vue
index 6395318af..0ca16f10e 100644
--- a/resources/assets/js/components/PostComponent.vue
+++ b/resources/assets/js/components/PostComponent.vue
@@ -616,6 +616,8 @@
Block
Unblock
Report
+ Archive
+ Unarchive
Delete
Cancel
@@ -1757,6 +1759,29 @@ export default {
});
},
+ archivePost(status) {
+ if(window.confirm('Are you sure you want to archive this post?') == false) {
+ return;
+ }
+
+ axios.post('/api/pixelfed/v2/status/' + status.id + '/archive')
+ .then(res => {
+ this.$refs.ctxModal.hide();
+ window.location.href = '/';
+ });
+ },
+
+ unarchivePost(status) {
+ if(window.confirm('Are you sure you want to unarchive this post?') == false) {
+ return;
+ }
+
+ axios.post('/api/pixelfed/v2/status/' + status.id + '/unarchive')
+ .then(res => {
+ this.$refs.ctxModal.hide();
+ });
+ }
+
},
}
diff --git a/resources/assets/js/components/Profile.vue b/resources/assets/js/components/Profile.vue
index 6545a8eae..83d524369 100644
--- a/resources/assets/js/components/Profile.vue
+++ b/resources/assets/js/components/Profile.vue
@@ -181,64 +181,68 @@
SAVED
+
+ ARCHIVES
+
-
+
How do I add a description to each photo or video for the visually impaired?
@@ -94,8 +94,8 @@
Image descriptions are federated to instances where supported.
-
-
+
+
What types of photos or videos can I upload?
@@ -104,14 +104,14 @@
You can upload the following media types:
- @foreach(explode(',', config('pixelfed.media_types')) as $type)
+ @foreach(explode(',', config_cache('pixelfed.media_types')) as $type)
- {{$type}}
@endforeach
- {{--
+ {{--
What is the limit for photo and video file sizes?
@@ -122,7 +122,7 @@
--}}
- {{--
+ {{--
When I share a photo, what's the image resolution?
@@ -133,7 +133,7 @@
--}}
- {{--
+ {{--
Can I edit my post captions, photos or videos after sharing them?
@@ -144,7 +144,7 @@
--}}
-
+
How can I disable comments/replies on my post?
@@ -159,7 +159,7 @@
-
+
How many people can I tag or mention in my comments or posts?
@@ -171,4 +171,55 @@
-@endsection
\ No newline at end of file
+
+
+
+ What does archive mean?
+
+
+
+ You can archive your posts which prevents anyone from interacting or viewing it.
+
+ Archived posts cannot be deleted or otherwise interacted with. You may not recieve interactions (comments, likes, shares) from other servers while a post is archived.
+
+
+
+
+
+
+
+
+ How can I archive my posts?
+
+
+
+ To archive your posts:
+
+ - Navigate to the post
+ - Open the menu, click the or button
+ - Click on Archive
+
+
+
+
+
+
+
+
+ How do I unarchive my posts?
+
+
+
+ To unarchive your posts:
+
+ - Navigate to your profile
+ - Click on the ARCHIVES tab
+ - Scroll to the post you want to unarchive
+ - Open the menu, click the or button
+ - Click on Unarchive
+
+
+
+
+
+@endsection
diff --git a/routes/web.php b/routes/web.php
index 77e834b2f..21bee6aaf 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -200,6 +200,9 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
Route::get('discover/posts/places', 'DiscoverController@trendingPlaces');
Route::get('seasonal/yir', 'SeasonalController@getData');
Route::post('seasonal/yir', 'SeasonalController@store');
+ Route::post('status/{id}/archive', 'ApiController@archive');
+ Route::post('status/{id}/unarchive', 'ApiController@unarchive');
+ Route::get('statuses/archives', 'ApiController@archivedPosts');
});
});