Merge pull request #2496 from pixelfed/staging

Staging
pull/2511/head
daniel 5 years ago committed by GitHub
commit d652de6f1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -135,6 +135,10 @@
- Updated NotificationTransformer, add missing types. ([3a428366](https://github.com/pixelfed/pixelfed/commit/3a428366)) - Updated NotificationTransformer, add missing types. ([3a428366](https://github.com/pixelfed/pixelfed/commit/3a428366))
- Updated StatusService, fix json bug. ([1ea2db74](https://github.com/pixelfed/pixelfed/commit/1ea2db74)) - Updated StatusService, fix json bug. ([1ea2db74](https://github.com/pixelfed/pixelfed/commit/1ea2db74))
- Updated NotificationTransformer, handle tagged deletes. ([881fa865](https://github.com/pixelfed/pixelfed/commit/881fa865)) - Updated NotificationTransformer, handle tagged deletes. ([881fa865](https://github.com/pixelfed/pixelfed/commit/881fa865))
- Updated horizon config, add new default values. ([90c8a721](https://github.com/pixelfed/pixelfed/commit/90c8a721))
- Updated ComposeModal, add maxlength attribute to alt text input. Fixes ([#2490](https://github.com/pixelfed/pixelfed/issues/2490)). ([526b5531](https://github.com/pixelfed/pixelfed/commit/526b5531))
- Updated PublicApiController, add state endpoint. ([9fc5a80c](https://github.com/pixelfed/pixelfed/commit/9fc5a80c))
- Updated PostComponent, add reply modal. ([a10d851f](https://github.com/pixelfed/pixelfed/commit/a10d851f))
## [v0.10.9 (2020-04-17)](https://github.com/pixelfed/pixelfed/compare/v0.10.8...v0.10.9) ## [v0.10.9 (2020-04-17)](https://github.com/pixelfed/pixelfed/compare/v0.10.8...v0.10.9)
### Added ### Added

@ -92,32 +92,47 @@ class PublicApiController extends Controller
$item = new Fractal\Resource\Item($status, new StatusStatelessTransformer()); $item = new Fractal\Resource\Item($status, new StatusStatelessTransformer());
$res = [ $res = [
'status' => $this->fractal->createData($item)->toArray(), 'status' => $this->fractal->createData($item)->toArray(),
'user' => [],
'likes' => [],
'shares' => [],
'reactions' => [
'liked' => false,
'shared' => false,
'bookmarked' => false,
],
]; ];
return response()->json($res, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES); return $res;
}); });
return $res; return response()->json($res);
} }
$item = new Fractal\Resource\Item($status, new StatusTransformer()); $item = new Fractal\Resource\Item($status, new StatusStatelessTransformer());
$res = [ $res = [
'status' => $this->fractal->createData($item)->toArray(), 'status' => $this->fractal->createData($item)->toArray(),
'user' => $this->getUserData($request->user()), ];
'likes' => $this->getLikes($status), return response()->json($res);
'shares' => $this->getShares($status), }
public function statusState(Request $request, $username, int $postid)
{
$profile = Profile::whereUsername($username)->whereNull('status')->firstOrFail();
$status = Status::whereProfileId($profile->id)->findOrFail($postid);
$this->scopeCheck($profile, $status);
if(!Auth::check()) {
$res = [
'user' => [],
'likes' => [],
'shares' => [],
'reactions' => [
'liked' => false,
'shared' => false,
'bookmarked' => false,
],
];
return response()->json($res);
}
$res = [
'user' => $this->getUserData($request->user()),
'likes' => [],
'shares' => [],
'reactions' => [ 'reactions' => [
'liked' => $status->liked(), 'liked' => (bool) $status->liked(),
'shared' => $status->shared(), 'shared' => (bool) $status->shared(),
'bookmarked' => $status->bookmarked(), 'bookmarked' => (bool) $status->bookmarked(),
], ],
]; ];
return response()->json($res, 200, [], JSON_PRETTY_PRINT); return response()->json($res);
} }
public function statusComments(Request $request, $username, int $postId) public function statusComments(Request $request, $username, int $postId)

@ -97,7 +97,29 @@ return [
'trim' => [ 'trim' => [
'recent' => 60, 'recent' => 60,
'pending' => 60,
'completed' => 60,
'recent_failed' => 10080,
'failed' => 10080, 'failed' => 10080,
'monitored' => 10080,
],
/*
|--------------------------------------------------------------------------
| Metrics
|--------------------------------------------------------------------------
|
| Here you can configure how many snapshots should be kept to display in
| the metrics graph. This will get used in combination with Horizon's
| `horizon:snapshot` schedule to define how long to retain metrics.
|
*/
'metrics' => [
'trim_snapshots' => [
'job' => 24,
'queue' => 24,
],
], ],
/* /*
@ -142,21 +164,25 @@ return [
'environments' => [ 'environments' => [
'production' => [ 'production' => [
'supervisor-1' => [ 'supervisor-1' => [
'connection' => 'redis', 'connection' => 'redis',
'queue' => ['high', 'default', 'feed'], 'queue' => ['high', 'default', 'feed'],
'balance' => 'auto', 'balance' => 'auto',
'processes' => 20, 'maxProcesses' => 20,
'tries' => 3, 'memory' => 128,
'tries' => 3,
'nice' => 0,
], ],
], ],
'local' => [ 'local' => [
'supervisor-1' => [ 'supervisor-1' => [
'connection' => 'redis', 'connection' => 'redis',
'queue' => ['high', 'default', 'feed'], 'queue' => ['high', 'default', 'feed'],
'balance' => 'auto', 'balance' => 'auto',
'processes' => 20, 'maxProcesses' => 20,
'tries' => 3, 'memory' => 128,
'tries' => 3,
'nice' => 0,
], ],
], ],
], ],

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -11,23 +11,23 @@
"/js/collectioncompose.js": "/js/collectioncompose.js?id=c6a07cb79dd7d6c7b8a0", "/js/collectioncompose.js": "/js/collectioncompose.js?id=c6a07cb79dd7d6c7b8a0",
"/js/collections.js": "/js/collections.js?id=6f64a9032085ebac28b3", "/js/collections.js": "/js/collections.js?id=6f64a9032085ebac28b3",
"/js/components.js": "/js/components.js?id=88296701f1382d285031", "/js/components.js": "/js/components.js?id=88296701f1382d285031",
"/js/compose.js": "/js/compose.js?id=cd4e13a102450aa558cb", "/js/compose.js": "/js/compose.js?id=1848b13369edc4e791ec",
"/js/compose-classic.js": "/js/compose-classic.js?id=283f19c895f4118a2a8b", "/js/compose-classic.js": "/js/compose-classic.js?id=283f19c895f4118a2a8b",
"/js/developers.js": "/js/developers.js?id=f75deca5ccf47d43eb07", "/js/developers.js": "/js/developers.js?id=f75deca5ccf47d43eb07",
"/js/direct.js": "/js/direct.js?id=e1e4a830bfedc1870db1", "/js/direct.js": "/js/direct.js?id=e1e4a830bfedc1870db1",
"/js/discover.js": "/js/discover.js?id=87071f23fc6d7118c66a", "/js/discover.js": "/js/discover.js?id=87071f23fc6d7118c66a",
"/js/hashtag.js": "/js/hashtag.js?id=4ebd78fde7fe65f5772c", "/js/hashtag.js": "/js/hashtag.js?id=4ebd78fde7fe65f5772c",
"/js/loops.js": "/js/loops.js?id=1dcb3790eb9ea4ea5848", "/js/loops.js": "/js/loops.js?id=1dcb3790eb9ea4ea5848",
"/js/memoryprofile.js": "/js/memoryprofile.js?id=828e26d71b4330fedc1b", "/js/memoryprofile.js": "/js/memoryprofile.js?id=75ea0503eca4f7ad3642",
"/js/mode-dot.js": "/js/mode-dot.js?id=dd9c87024fbaa8e75ac4", "/js/mode-dot.js": "/js/mode-dot.js?id=dd9c87024fbaa8e75ac4",
"/js/profile.js": "/js/profile.js?id=559d809df9a10adc091a", "/js/profile.js": "/js/profile.js?id=889a57bbb59e82d2d436",
"/js/profile-directory.js": "/js/profile-directory.js?id=855a548efdf56b8594bf", "/js/profile-directory.js": "/js/profile-directory.js?id=855a548efdf56b8594bf",
"/js/quill.js": "/js/quill.js?id=866b31b9b9540305751d", "/js/quill.js": "/js/quill.js?id=866b31b9b9540305751d",
"/js/rempos.js": "/js/rempos.js?id=29dacb6e0ce2c936e5cd", "/js/rempos.js": "/js/rempos.js?id=5d2841b753dc76ccd8ed",
"/js/rempro.js": "/js/rempro.js?id=6e7fc68a65bf82d5aec8", "/js/rempro.js": "/js/rempro.js?id=6e7fc68a65bf82d5aec8",
"/js/search.js": "/js/search.js?id=5467143312ebae07695b", "/js/search.js": "/js/search.js?id=5467143312ebae07695b",
"/js/status.js": "/js/status.js?id=70f5597c1069d7ead4bb", "/js/status.js": "/js/status.js?id=c64d7542738b57eff9a7",
"/js/story-compose.js": "/js/story-compose.js?id=13f9606a3c4ce7acf17b", "/js/story-compose.js": "/js/story-compose.js?id=13f9606a3c4ce7acf17b",
"/js/theme-monokai.js": "/js/theme-monokai.js?id=8842103833ba4861bcfa", "/js/theme-monokai.js": "/js/theme-monokai.js?id=8842103833ba4861bcfa",
"/js/timeline.js": "/js/timeline.js?id=44dae7cd501b4b9adce2" "/js/timeline.js": "/js/timeline.js?id=b8504c8ae22a19804401"
} }

@ -327,6 +327,7 @@
</div> </div>
<p class="font-weight-bold text-center small text-muted pt-3 mb-0">When you tag someone, they are sent a notification.<br>For more information on tagging, <a href="#" class="text-primary" @click.prevent="showTagHelpCard()">click here</a>.</p> <p class="font-weight-bold text-center small text-muted pt-3 mb-0">When you tag someone, they are sent a notification.<br>For more information on tagging, <a href="#" class="text-primary" @click.prevent="showTagHelpCard()">click here</a>.</p>
</div> </div>
<div v-if="page == 'tagPeopleHelp'" class="w-100 h-100 p-3"> <div v-if="page == 'tagPeopleHelp'" class="w-100 h-100 p-3">
<p class="mb-0 text-center py-3 px-2 lead">Tagging someone is like mentioning them, with the option to make it private between you.</p> <p class="mb-0 text-center py-3 px-2 lead">Tagging someone is like mentioning them, with the option to make it private between you.</p>
<p class="mb-3 py-3 px-2 font-weight-lighter"> <p class="mb-3 py-3 px-2 font-weight-lighter">
@ -420,7 +421,7 @@
<div class="media"> <div class="media">
<img :src="m.preview_url" class="mr-3" width="50px" height="50px"> <img :src="m.preview_url" class="mr-3" width="50px" height="50px">
<div class="media-body"> <div class="media-body">
<textarea class="form-control" v-model="m.alt" placeholder="Add a media description here..."></textarea> <textarea class="form-control" v-model="m.alt" placeholder="Add a media description here..." maxlength="140"></textarea>
<p class="help-text small text-right text-muted mb-0">{{m.alt ? m.alt.length : 0}}/140</p> <p class="help-text small text-right text-muted mb-0">{{m.alt ? m.alt.length : 0}}/140</p>
</div> </div>
</div> </div>
@ -468,7 +469,7 @@
<div class="media-body"> <div class="media-body">
<div class="form-group"> <div class="form-group">
<label class="font-weight-bold text-muted small">Media Description</label> <label class="font-weight-bold text-muted small">Media Description</label>
<textarea class="form-control" v-model="media[carouselCursor].alt" placeholder="Add a media description here..."></textarea> <textarea class="form-control" v-model="media[carouselCursor].alt" placeholder="Add a media description here..." maxlength="140"></textarea>
<p class="help-text small text-muted mb-0 d-flex justify-content-between"> <p class="help-text small text-muted mb-0 d-flex justify-content-between">
<span>Describe your photo for people with visual impairments.</span> <span>Describe your photo for people with visual impairments.</span>
<span>{{media[carouselCursor].alt ? media[carouselCursor].alt.length : 0}}/140</span> <span>{{media[carouselCursor].alt ? media[carouselCursor].alt.length : 0}}/140</span>

@ -35,24 +35,10 @@
</div> </div>
<div v-if="user != false" class="float-right"> <div v-if="user != false" class="float-right">
<div class="post-actions"> <div class="post-actions">
<div class="dropdown"> <div>
<button class="btn btn-link text-dark no-caret dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="Post options"> <button class="btn btn-link text-dark no-caret" title="Post options" @click="ctxMenu()">
<span class="fas fa-ellipsis-v text-muted"></span> <span class="fas fa-ellipsis-v text-muted"></span>
</button> </button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenuButton">
<a class="dropdown-item font-weight-bold" @click="copyPostUrl()">Copy Post Url</a>
<a class="dropdown-item font-weight-bold" @click="showEmbedPostModal()">Embed</a>
<div v-if="!owner()">
<a class="dropdown-item font-weight-bold" :href="reportUrl()">Report</a>
<a class="dropdown-item font-weight-bold" v-on:click="muteProfile()">Mute Profile</a>
<a class="dropdown-item font-weight-bold" v-on:click="blockProfile()">Block Profile</a>
</div>
<div v-if="ownerOrAdmin()">
<a class="dropdown-item font-weight-bold" href="#" v-on:click.prevent="toggleCommentVisibility">{{ showComments ? 'Disable' : 'Enable'}} Comments</a>
<a v-if="canEdit" class="dropdown-item font-weight-bold" :href="editUrl()">Edit</a>
<a class="dropdown-item font-weight-bold text-danger" v-on:click="deletePost(status)">Delete</a>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -108,30 +94,16 @@
</div> </div>
<div class="float-right"> <div class="float-right">
<div class="post-actions"> <div class="post-actions">
<div v-if="user != false" class="dropdown"> <div v-if="user != false">
<button class="btn btn-link text-dark no-caret dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="Post options"> <button class="btn btn-link text-dark no-caret" title="Post options" @click="ctxMenu()">
<span class="fas fa-ellipsis-v text-muted"></span> <span class="fas fa-ellipsis-v text-muted"></span>
</button> </button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenuButton">
<a class="dropdown-item font-weight-bold" @click="copyPostUrl()">Copy Post Url</a>
<a class="dropdown-item font-weight-bold" @click="showEmbedPostModal()">Embed</a>
<span v-if="!owner()">
<a class="dropdown-item font-weight-bold" :href="reportUrl()">Report</a>
<a class="dropdown-item font-weight-bold" v-on:click="muteProfile">Mute Profile</a>
<a class="dropdown-item font-weight-bold" v-on:click="blockProfile">Block Profile</a>
</span>
<span v-if="ownerOrAdmin()">
<a class="dropdown-item font-weight-bold" href="#" v-on:click.prevent="toggleCommentVisibility">{{ showComments ? 'Disable' : 'Enable'}} Comments</a>
<a v-if="canEdit" class="dropdown-item font-weight-bold" :href="editUrl()">Edit</a>
<a class="dropdown-item font-weight-bold text-danger" v-on:click="deletePost">Delete</a>
</span>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="d-flex flex-md-column flex-column-reverse h-100" style="overflow-y: auto;"> <div class="d-flex flex-md-column flex-column-reverse h-100" style="overflow-y: auto;">
<div class="card-body status-comments pb-5 pt-0"> <div class="card-body status-comments pt-0">
<div class="status-comment"> <div class="status-comment">
<div v-if="status.content.length" class="pt-3"> <div v-if="status.content.length" class="pt-3">
<div v-if="showCaption != true"> <div v-if="showCaption != true">
@ -227,7 +199,12 @@
</div> </div>
</div> </div>
<div class="card-body flex-grow-0 py-1"> <div v-if="reactionBarLoading" class="card-body flex-grow-0 py-4 text-center">
<div class="spinner-border" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
<div v-else class="card-body flex-grow-0 py-1">
<div v-if="loaded && user.hasOwnProperty('id')" class="reactions my-2 pb-1 d-flex justify-content-between"> <div v-if="loaded && user.hasOwnProperty('id')" class="reactions my-2 pb-1 d-flex justify-content-between">
<h3 v-bind:class="[reactions.liked ? 'fas fa-heart text-danger mr-3 m-0 cursor-pointer' : 'far fa-heart pr-3 m-0 like-btn cursor-pointer']" title="Like" v-on:click="likeStatus"></h3> <h3 v-bind:class="[reactions.liked ? 'fas fa-heart text-danger mr-3 m-0 cursor-pointer' : 'far fa-heart pr-3 m-0 like-btn cursor-pointer']" title="Like" v-on:click="likeStatus"></h3>
<h3 v-if="!status.comments_disabled" class="far fa-comment mr-3 m-0 cursor-pointer" title="Comment" v-on:click="replyFocus(status)"></h3> <h3 v-if="!status.comments_disabled" class="far fa-comment mr-3 m-0 cursor-pointer" title="Comment" v-on:click="replyFocus(status)"></h3>
@ -252,18 +229,13 @@
</div> </div>
</div> </div>
</div> </div>
<!-- <div v-if="showComments && user.length !== 0" class="card-footer bg-white px-2 py-0">
<ul class="nav align-items-center emoji-reactions" style="overflow-x: scroll;flex-wrap: unset;">
<li class="nav-item" v-on:click="emojiReaction" v-for="e in emoji">{{e}}</li>
</ul>
</div> -->
<div v-if="showComments" class="card-footer bg-white sticky-md-bottom p-0"> <div v-if="showComments" class="card-footer bg-white sticky-md-bottom p-0">
<div v-if="user.length == 0" class="comment-form-guest p-3"> <div v-if="user.length == 0" class="comment-form-guest p-3">
<a href="/login">Login</a> to like or comment. <a href="/login">Login</a> to like or comment.
</div> </div>
<form v-else class="border-0 rounded-0 align-middle" method="post" action="/i/comment" :data-id="statusId" data-truncate="false"> <form v-else class="border-0 rounded-0 align-middle" method="post" action="/i/comment" :data-id="statusId" data-truncate="false">
<textarea class="form-control border-0 rounded-0" name="comment" placeholder="Add a comment…" autocomplete="off" autocorrect="off" style="height:56px;line-height: 18px;max-height:80px;resize: none; padding-right:4.2rem;" v-model="replyText"></textarea> <textarea class="form-control border-0 rounded-0" name="comment" placeholder="Add a comment…" autocomplete="off" autocorrect="off" style="height:56px;line-height: 18px;max-height:80px;resize: none; padding-right:4.2rem;" @click="replyFocus(status)"></textarea>
<input type="button" value="Post" class="d-inline-block btn btn-link font-weight-bold reply-btn text-decoration-none" v-on:click.prevent="postReply" :disabled="replyText.length == 0" /> <input type="button" value="Post" class="d-inline-block btn btn-link font-weight-bold reply-btn text-decoration-none" disabled/>
</form> </form>
</div> </div>
</div> </div>
@ -271,9 +243,6 @@
</div> </div>
</div> </div>
<div class="container" v-if="showProfileMorePosts"> <div class="container" v-if="showProfileMorePosts">
<!-- <div class="py-4">
<hr>
</div> -->
<p class="text-lighter px-3 mt-5" style="font-weight: 600;font-size: 15px;">More posts from <a :href="'/'+statusUsername" class="text-dark">{{this.statusUsername}}</a></p> <p class="text-lighter px-3 mt-5" style="font-weight: 600;font-size: 15px;">More posts from <a :href="'/'+statusUsername" class="text-dark">{{this.statusUsername}}</a></p>
<div class="profile-timeline mt-md-4"> <div class="profile-timeline mt-md-4">
<div class="row"> <div class="row">
@ -474,6 +443,7 @@
</div> </div>
</div> </div>
</div> </div>
<b-modal ref="likesModal" <b-modal ref="likesModal"
id="l-modal" id="l-modal"
hide-footer hide-footer
@ -512,9 +482,9 @@
hide-footer hide-footer
centered centered
title="Shares" title="Shares"
body-class="list-group-flush p-0"> body-class="list-group-flush py-3 px-0">
<div class="list-group"> <div class="list-group">
<div class="list-group-item border-0" v-for="(user, index) in shares" :key="'modal_shares_'+index"> <div class="list-group-item border-0 py-1" v-for="(user, index) in shares" :key="'modal_shares_'+index">
<div class="media"> <div class="media">
<a :href="user.url"> <a :href="user.url">
<img class="mr-3 rounded-circle box-shadow" :src="user.avatar" :alt="user.username + 's avatar'" width="30px"> <img class="mr-3 rounded-circle box-shadow" :src="user.avatar" :alt="user.username + 's avatar'" width="30px">
@ -615,6 +585,88 @@
</div> </div>
<p class="mb-0 text-center small text-muted font-weight-bold"><a href="/site/kb/tagging-people">Learn more</a> about Tagging People.</p> <p class="mb-0 text-center small text-muted font-weight-bold"><a href="/site/kb/tagging-people">Learn more</a> about Tagging People.</p>
</b-modal> </b-modal>
<b-modal ref="ctxModal"
id="ctx-modal"
hide-header
hide-footer
centered
rounded
size="sm"
body-class="list-group-flush p-0 rounded">
<div class="list-group text-center">
<div v-if="user && user.id != status.account.id && relationship && relationship.following" class="list-group-item rounded cursor-pointer font-weight-bold text-danger" @click="ctxMenuUnfollow()">Unfollow</div>
<div v-if="user && user.id != status.account.id && relationship && !relationship.following" class="list-group-item rounded cursor-pointer font-weight-bold text-primary" @click="ctxMenuFollow()">Follow</div>
<div v-if="status && status.local == true" class="list-group-item rounded cursor-pointer" @click="showEmbedPostModal()">Embed</div>
<div class="list-group-item rounded cursor-pointer" @click="ctxMenuCopyLink()">Copy Link</div>
<div v-if="status && user.id == status.account.id" class="list-group-item rounded cursor-pointer" @click="toggleCommentVisibility">{{ showComments ? 'Disable' : 'Enable'}} Comments</div>
<a v-if="status && user.id == status.account.id" class="list-group-item rounded cursor-pointer text-dark text-decoration-none" :href="editUrl()">Edit</a>
<div v-if="user && user.is_admin == true" class="list-group-item rounded cursor-pointer" @click="ctxModMenu()">ModTools</div>
<div v-if="status && user.id != status.account.id && !relationship.blocking && !user.is_admin" class="list-group-item rounded cursor-pointer font-weight-bold text-danger" @click="blockProfile()">Block</div>
<div v-if="status && user.id != status.account.id && relationship.blocking && !user.is_admin" class="list-group-item rounded cursor-pointer font-weight-bold text-danger" @click="unblockProfile()">Unblock</div>
<a v-if="user && user.id != status.account.id && !user.is_admin" class="list-group-item rounded cursor-pointer font-weight-bold text-danger text-decoration-none" :href="reportUrl()">Report</a>
<div v-if="status && (user.is_admin || user.id == status.account.id)" class="list-group-item rounded cursor-pointer font-weight-bold text-danger" @click="deletePost(ctxMenuStatus)">Delete</div>
<div class="list-group-item rounded cursor-pointer text-lighter" @click="closeCtxMenu()">Cancel</div>
</div>
</b-modal>
<b-modal ref="ctxModModal"
id="ctx-mod-modal"
hide-header
hide-footer
centered
rounded
size="sm"
body-class="list-group-flush p-0 rounded">
<div class="list-group text-center">
<div class="list-group-item rounded cursor-pointer" @click="toggleCommentVisibility">{{ showComments ? 'Disable' : 'Enable'}} Comments</div>
<div class="list-group-item rounded cursor-pointer" @click="moderatePost('unlist')">Unlist from Timelines</div>
<div v-if="status.sensitive" class="list-group-item rounded cursor-pointer" @click="moderatePost('remcw')">Remove Content Warning</div>
<div v-else class="list-group-item rounded cursor-pointer" @click="moderatePost('addcw')">Add Content Warning</div>
<div class="list-group-item rounded cursor-pointer text-lighter" @click="ctxModMenuClose()">Cancel</div>
</div>
</b-modal>
<b-modal ref="replyModal"
id="ctx-reply-modal"
hide-footer
centered
rounded
:title-html="replyingToUsername ? 'Reply to <span class=text-dark>' + replyingToUsername + '</span>' : ''"
title-tag="p"
title-class="font-weight-bold text-muted"
size="md"
body-class="p-2 rounded">
<div>
<textarea class="form-control" rows="4" style="border: none; font-size: 18px; resize: none; white-space: pre-wrap;outline: none;" placeholder="Reply here ..." v-model="replyText">
</textarea>
<div class="border-top border-bottom my-2">
<ul class="nav align-items-center emoji-reactions" style="overflow-x: scroll;flex-wrap: unset;">
<li class="nav-item" v-on:click="emojiReaction(status)" v-for="e in emoji">{{e}}</li>
</ul>
</div>
<div class="d-flex justify-content-between align-items-center">
<div>
<span class="pl-2 small text-muted font-weight-bold text-monospace">
<span :class="[replyText.length > config.uploader.max_caption_length ? 'text-danger':'text-dark']">{{replyText.length > config.uploader.max_caption_length ? config.uploader.max_caption_length - replyText.length : replyText.length}}</span>/{{config.uploader.max_caption_length}}
</span>
</div>
<div class="d-flex align-items-center">
<div class="custom-control custom-switch mr-3">
<input type="checkbox" class="custom-control-input" id="replyModalCWSwitch" v-model="replySensitive">
<label :class="[replySensitive ? 'custom-control-label font-weight-bold text-dark':'custom-control-label text-lighter']" for="replyModalCWSwitch">Mark as NSFW</label>
</div>
<!-- <select class="custom-select custom-select-sm my-0 mr-2">
<option value="public" selected="">Public</option>
<option value="unlisted">Unlisted</option>
<option value="followers">Followers Only</option>
</select> -->
<button class="btn btn-primary btn-sm py-2 px-4 lead text-uppercase font-weight-bold" v-on:click.prevent="postReply()" :disabled="replyText.length == 0">
{{replySending == true ? 'POSTING' : 'POST'}}
</button>
</div>
</div>
</div>
</b-modal>
</div> </div>
</template> </template>
@ -742,6 +794,7 @@ export default {
loaded: false, loaded: false,
loading: null, loading: null,
replyingToId: this.statusId, replyingToId: this.statusId,
replyingToUsername: this.statusUsername,
replyToIndex: 0, replyToIndex: 0,
replySending: false, replySending: false,
emoji: window.App.util.emoji, emoji: window.App.util.emoji,
@ -753,9 +806,10 @@ export default {
ctxEmbedShowLikes: false, ctxEmbedShowLikes: false,
ctxEmbedCompactMode: false, ctxEmbedCompactMode: false,
layout: this.profileLayout, layout: this.profileLayout,
canEdit: false,
showProfileMorePosts: false, showProfileMorePosts: false,
profileMorePosts: [] profileMorePosts: [],
replySending: false,
reactionBarLoading: true,
} }
}, },
watch: { watch: {
@ -811,16 +865,6 @@ export default {
}, },
methods: { methods: {
showMuteBlock() {
let sid = this.status.account.id;
let uid = this.user.id;
if(sid == uid) {
$('.post-actions .menu-author').removeClass('d-none');
} else {
$('.post-actions .menu-user').removeClass('d-none');
}
},
reportUrl() { reportUrl() {
return '/i/report?type=post&id=' + this.status.id; return '/i/report?type=post&id=' + this.status.id;
}, },
@ -839,33 +883,20 @@ export default {
axios.get('/api/v2/profile/'+this.statusUsername+'/status/'+this.statusId) axios.get('/api/v2/profile/'+this.statusUsername+'/status/'+this.statusId)
.then(response => { .then(response => {
self.status = response.data.status; self.status = response.data.status;
self.user = response.data.user;
window._sharedData.curUser = self.user;
window.App.util.navatar();
self.media = self.status.media_attachments; self.media = self.status.media_attachments;
self.reactions = response.data.reactions;
self.likes = response.data.likes;
self.shares = response.data.shares;
self.likesPage = 2; self.likesPage = 2;
self.sharesPage = 2; self.sharesPage = 2;
this.showMuteBlock();
self.showCaption = !response.data.status.sensitive; self.showCaption = !response.data.status.sensitive;
if(self.status.comments_disabled == false) { if(self.status.comments_disabled == false) {
self.showComments = true; self.showComments = true;
this.fetchComments(); this.fetchComments();
} }
if(this.ownerOrAdmin()) {
let od = new Date(this.status.created_at).getTime() + (1 * 24 * 60 * 60 * 1000);
let now = new Date().getTime();
if(od > now) {
this.canEdit = true;
}
}
this.loaded = true; this.loaded = true;
setTimeout(function() { setTimeout(function() {
self.fetchProfilePosts(); self.fetchProfilePosts();
}, 3000); }, 3000);
setTimeout(function() { setTimeout(function() {
self.fetchState();
document.querySelectorAll('.status-comment .comment-text a').forEach(function(i, e) { document.querySelectorAll('.status-comment .comment-text a').forEach(function(i, e) {
if(i.href.startsWith(window.location.origin)) { if(i.href.startsWith(window.location.origin)) {
return; return;
@ -882,6 +913,20 @@ export default {
}); });
}, },
fetchState() {
let self = this;
axios.get('/api/v2/profile/'+this.statusUsername+'/status/'+this.statusId+'/state')
.then(res => {
self.user = res.data.user;
window._sharedData.curUser = self.user;
window.App.util.navatar();
self.likes = res.data.likes;
self.shares = res.data.shares;
self.reactions = res.data.reactions;
self.reactionBarLoading = false;
});
},
likesModal() { likesModal() {
if($('body').hasClass('loggedIn') == false) { if($('body').hasClass('loggedIn') == false) {
window.location.href = '/login?next=' + encodeURIComponent('/p/' + this.status.shortcode); window.location.href = '/login?next=' + encodeURIComponent('/p/' + this.status.shortcode);
@ -890,14 +935,31 @@ export default {
if(this.status.favourites_count == 0) { if(this.status.favourites_count == 0) {
return; return;
} }
this.$refs.likesModal.show(); if(this.likes.length) {
this.$refs.likesModal.show();
return;
}
axios.get('/api/v2/likes/profile/'+this.statusUsername+'/status/'+this.statusId)
.then(res => {
this.likes = res.data.data;
this.$refs.likesModal.show();
});
}, },
sharesModal() { sharesModal() {
if(this.status.reblogs_count == 0 || $('body').hasClass('loggedIn') == false) { if(this.status.reblogs_count == 0 || $('body').hasClass('loggedIn') == false) {
window.location.href = '/login?next=' + encodeURIComponent('/p/' + this.status.shortcode);
return;
}
if(this.shares.length) {
this.$refs.sharesModal.show();
return; return;
} }
this.$refs.sharesModal.show(); axios.get('/api/v2/shares/profile/'+this.statusUsername+'/status/'+this.statusId)
.then(res => {
this.shares = res.data.data;
this.$refs.sharesModal.show();
});
}, },
infiniteLikesHandler($state) { infiniteLikesHandler($state) {
@ -1010,31 +1072,35 @@ export default {
}); });
}, },
muteProfile() { blockProfile() {
if($('body').hasClass('loggedIn') == false) { if($('body').hasClass('loggedIn') == false) {
return; return;
} }
axios.post('/i/mute', { axios.post('/i/block', {
type: 'user', type: 'user',
item: this.status.account.id item: this.status.account.id
}).then(res => { }).then(res => {
swal('Success', 'You have successfully muted ' + this.status.account.acct, 'success'); this.$refs.ctxModal.hide();
this.relationship.blocking = true;
swal('Success', 'You have successfully blocked ' + this.status.account.acct, 'success');
}).catch(err => { }).catch(err => {
swal('Error', 'Something went wrong. Please try again later.', 'error'); swal('Error', 'Something went wrong. Please try again later.', 'error');
}); });
}, },
blockProfile() { unblockProfile() {
if($('body').hasClass('loggedIn') == false) { if($('body').hasClass('loggedIn') == false) {
return; return;
} }
axios.post('/i/block', { axios.post('/i/unblock', {
type: 'user', type: 'user',
item: this.status.account.id item: this.status.account.id
}).then(res => { }).then(res => {
swal('Success', 'You have successfully blocked ' + this.status.account.acct, 'success'); this.relationship.blocking = false;
this.$refs.ctxModal.hide();
swal('Success', 'You have successfully unblocked ' + this.status.account.acct, 'success');
}).catch(err => { }).catch(err => {
swal('Error', 'Something went wrong. Please try again later.', 'error'); swal('Error', 'Something went wrong. Please try again later.', 'error');
}); });
@ -1082,6 +1148,7 @@ export default {
postReply() { postReply() {
let self = this; let self = this;
this.replySending = true;
if(this.replyText.length == 0 || if(this.replyText.length == 0 ||
this.replyText.trim() == '@'+this.status.account.acct) { this.replyText.trim() == '@'+this.status.account.acct) {
self.replyText = null; self.replyText = null;
@ -1106,7 +1173,7 @@ export default {
self.results.unshift(entity); self.results.unshift(entity);
} }
let elem = $('.status-comments')[0]; let elem = $('.status-comments')[0];
elem.scrollTop = elem.clientHeight; elem.scrollTop = elem.clientHeight * 2;
} else { } else {
if(self.replyToIndex >= 0) { if(self.replyToIndex >= 0) {
let el = self.results[self.replyToIndex]; let el = self.results[self.replyToIndex];
@ -1114,6 +1181,8 @@ export default {
el.reply_count = el.reply_count + 1; el.reply_count = el.reply_count + 1;
} }
} }
self.$refs.replyModal.hide();
self.replySending = false;
}); });
}, },
@ -1147,15 +1216,25 @@ export default {
}, },
replyFocus(e, index, prependUsername = false) { replyFocus(e, index, prependUsername = false) {
if($('body').hasClass('loggedIn') == false) {
this.redirect('/login?next=' + encodeURIComponent(window.location.pathname));
return;
}
if(this.status.comments_disabled) {
return;
}
this.replyToIndex = index; this.replyToIndex = index;
this.replyingToId = e.id; this.replyingToId = e.id;
this.replyingToUsername = e.account.username;
this.reply_to_profile_id = e.account.id; this.reply_to_profile_id = e.account.id;
let username = e.account.local ? '@' + e.account.username + ' ' let username = e.account.local ? '@' + e.account.username + ' '
: '@' + e.account.acct + ' '; : '@' + e.account.acct + ' ';
if(prependUsername == true) { if(prependUsername == true) {
this.replyText = username; this.replyText = username;
} }
$('textarea[name="comment"]').focus(); this.$refs.replyModal.show();
}, },
fetchComments() { fetchComments() {
@ -1289,7 +1368,9 @@ export default {
item: self.status.id, item: self.status.id,
disableComments: false disableComments: false
}).then(function(res) { }).then(function(res) {
window.location.href = self.status.url; self.status.comments_disabled = false;
self.$refs.ctxModal.hide();
window.location.reload();
}).catch(function(err) { }).catch(function(err) {
return; return;
}); });
@ -1299,8 +1380,9 @@ export default {
item: self.status.id, item: self.status.id,
disableComments: true disableComments: true
}).then(function(res) { }).then(function(res) {
self.status.comments_disabled = false; self.status.comments_disabled = true;
self.showComments = false; self.showComments = false;
self.$refs.ctxModal.hide();
}).catch(function(err) { }).catch(function(err) {
return; return;
}); });
@ -1374,6 +1456,7 @@ export default {
showEmbedPostModal() { showEmbedPostModal() {
let mode = this.ctxEmbedCompactMode ? 'compact' : 'full'; let mode = this.ctxEmbedCompactMode ? 'compact' : 'full';
this.ctxEmbedPayload = window.App.util.embed.post(this.status.url, this.ctxEmbedShowCaption, this.ctxEmbedShowLikes, mode); this.ctxEmbedPayload = window.App.util.embed.post(this.status.url, this.ctxEmbedShowCaption, this.ctxEmbedShowLikes, mode);
this.$refs.ctxModal.hide();
this.$refs.embedModal.show(); this.$refs.embedModal.show();
}, },
@ -1461,10 +1544,166 @@ export default {
swal('An Error Occurred', 'Please try again later.', 'error'); swal('An Error Occurred', 'Please try again later.', 'error');
}); });
}, },
copyPostUrl() { copyPostUrl() {
navigator.clipboard.writeText(this.statusUrl); navigator.clipboard.writeText(this.statusUrl);
return; return;
} },
moderatePost(action, $event) {
let status = this.status;
let username = status.account.username;
let msg = '';
let self = this;
switch(action) {
case 'addcw':
msg = 'Are you sure you want to add a content warning to this post?';
swal({
title: 'Confirm',
text: msg,
icon: 'warning',
buttons: true,
dangerMode: true
}).then(res => {
if(res) {
axios.post('/api/v2/moderator/action', {
action: action,
item_id: status.id,
item_type: 'status'
}).then(res => {
swal('Success', 'Successfully added content warning', 'success');
status.sensitive = true;
self.ctxModMenuClose();
}).catch(err => {
swal(
'Error',
'Something went wrong, please try again later.',
'error'
);
self.ctxModMenuClose();
});
}
});
break;
case 'remcw':
msg = 'Are you sure you want to remove the content warning on this post?';
swal({
title: 'Confirm',
text: msg,
icon: 'warning',
buttons: true,
dangerMode: true
}).then(res => {
if(res) {
axios.post('/api/v2/moderator/action', {
action: action,
item_id: status.id,
item_type: 'status'
}).then(res => {
swal('Success', 'Successfully added content warning', 'success');
status.sensitive = false;
self.ctxModMenuClose();
}).catch(err => {
swal(
'Error',
'Something went wrong, please try again later.',
'error'
);
self.ctxModMenuClose();
});
}
});
break;
case 'unlist':
msg = 'Are you sure you want to unlist this post?';
swal({
title: 'Confirm',
text: msg,
icon: 'warning',
buttons: true,
dangerMode: true
}).then(res => {
if(res) {
axios.post('/api/v2/moderator/action', {
action: action,
item_id: status.id,
item_type: 'status'
}).then(res => {
// this.feed = this.feed.filter(f => {
// return f.id != status.id;
// });
swal('Success', 'Successfully unlisted post', 'success');
self.ctxModMenuClose();
}).catch(err => {
self.ctxModMenuClose();
swal(
'Error',
'Something went wrong, please try again later.',
'error'
);
});
}
});
break;
}
},
ctxMenu() {
this.$refs.ctxModal.show();
return;
},
closeCtxMenu(truncate) {
this.$refs.ctxModal.hide();
},
ctxModMenu() {
this.$refs.ctxModal.hide();
this.$refs.ctxModModal.show();
},
ctxModMenuClose() {
this.$refs.ctxModal.hide();
this.$refs.ctxModModal.hide();
},
ctxMenuCopyLink() {
let status = this.status;
navigator.clipboard.writeText(status.url);
this.closeCtxMenu();
return;
},
ctxMenuFollow() {
let id = this.status.account.id;
axios.post('/i/follow', {
item: id
}).then(res => {
let username = this.status.account.acct;
this.relationship.following = true;
this.$refs.ctxModal.hide();
setTimeout(function() {
swal('Follow successful!', 'You are now following ' + username, 'success');
}, 500);
});
},
ctxMenuUnfollow() {
let id = this.status.account.id;
axios.post('/i/follow', {
item: id
}).then(res => {
let username = this.status.account.acct;
this.relationship.following = false;
this.$refs.ctxModal.hide();
setTimeout(function() {
swal('Unfollow successful!', 'You are no longer following ' + username, 'success');
}, 500);
});
},
}, },
} }
</script> </script>

@ -57,35 +57,8 @@
<!-- a class="list-group-item font-weight-bold text-decoration-none" :href="status.url">Share</a> <!-- a class="list-group-item font-weight-bold text-decoration-none" :href="status.url">Share</a>
<a class="list-group-item font-weight-bold text-decoration-none" :href="status.url">Embed</a> --> <a class="list-group-item font-weight-bold text-decoration-none" :href="status.url">Embed</a> -->
<a class="list-group-item text-dark text-decoration-none" href="#" @click.prevent="hidePost(status)">Hide</a> <a class="list-group-item text-dark text-decoration-none" href="#" @click.prevent="hidePost(status)">Hide</a>
<a v-if="activeSession == true && !statusOwner(status)" class="list-group-item text-dark text-decoration-none" :href="reportUrl(status)">Report</a> <a v-if="activeSession == true && !statusOwner(status)" class="list-group-item text-danger font-weight-bold text-decoration-none" :href="reportUrl(status)">Report</a>
<a v-if="activeSession == true && !statusOwner(status)" class="list-group-item text-dark text-decoration-none" @click.prevent="muteProfile(status)" href="#">Mute Profile</a> <div v-if="activeSession == true && statusOwner(status) == true || profile.is_admin == true" class="list-group-item text-danger font-weight-bold cursor-pointer" @click.prevent="deletePost">Delete</div>
<a v-if="activeSession == true && !statusOwner(status)" class="list-group-item text-dark text-decoration-none" @click.prevent="blockProfile(status)" href="#">Block Profile</a>
<span v-if="activeSession == true && statusOwner(status) == true || profile.is_admin == true">
<a class="list-group-item text-danger text-decoration-none" @click.prevent="deletePost">Delete</a>
</span>
<span v-if="activeSession == true && profile.is_admin == true">
<a class="list-group-item text-dark text-decoration-none" v-on:click="moderatePost(status, 'autocw')" href="#">
<p class="mb-0">Enforce CW</p>
<p class="mb-0 small text-muted">Adds a CW to every post <br> made by this account.</p>
</a>
<a class="list-group-item text-dark text-decoration-none" v-on:click="moderatePost(status, 'noautolink')" href="#">
<p class="mb-0">No Autolinking</p>
<p class="mb-0 small text-muted">Do not transform mentions, <br> hashtags or urls into HTML.</p>
</a>
<a class="list-group-item text-dark text-decoration-none" v-on:click="moderatePost(status, 'unlisted')" href="#">
<p class="mb-0">Unlisted Posts</p>
<p class="mb-0 small text-muted">Removes account from <br> public/network timelines.</p>
</a>
<a class="list-group-item text-dark text-decoration-none" v-on:click="moderatePost(status, 'disable')" href="#">
<p class="mb-0">Disable Account</p>
<p class="mb-0 small text-muted">Temporarily disable account <br> until next time user log in.</p>
</a>
<a class="list-group-item text-dark text-decoration-none" v-on:click="moderatePost(status, 'suspend')" href="#">
<p class="mb-0">Suspend Account</p>
<p class="mb-0 small text-muted">This prevents any new interactions, <br> without deleting existing data.</p>
</a>
</span>
</div> </div>
</div> </div>
</div> </div>

@ -438,11 +438,11 @@
size="sm" size="sm"
body-class="list-group-flush p-0 rounded"> body-class="list-group-flush p-0 rounded">
<div class="list-group text-center"> <div class="list-group text-center">
<div v-if="ctxMenuStatus && ctxMenuStatus.account.id != profile.id" class="list-group-item rounded cursor-pointer font-weight-bold text-danger" @click="ctxMenuReportPost()">Report inappropriate</div> <div v-if="ctxMenuStatus && ctxMenuStatus.account.id != profile.id" class="list-group-item rounded cursor-pointer font-weight-bold text-danger" @click="ctxMenuReportPost()">Report</div>
<div v-if="ctxMenuStatus && ctxMenuStatus.account.id != profile.id && ctxMenuRelationship && ctxMenuRelationship.following" class="list-group-item rounded cursor-pointer font-weight-bold text-danger" @click="ctxMenuUnfollow()">Unfollow</div> <div v-if="ctxMenuStatus && ctxMenuStatus.account.id != profile.id && ctxMenuRelationship && ctxMenuRelationship.following" class="list-group-item rounded cursor-pointer font-weight-bold text-danger" @click="ctxMenuUnfollow()">Unfollow</div>
<div v-if="ctxMenuStatus && ctxMenuStatus.account.id != profile.id && ctxMenuRelationship && !ctxMenuRelationship.following" class="list-group-item rounded cursor-pointer font-weight-bold text-primary" @click="ctxMenuFollow()">Follow</div> <div v-if="ctxMenuStatus && ctxMenuStatus.account.id != profile.id && ctxMenuRelationship && !ctxMenuRelationship.following" class="list-group-item rounded cursor-pointer font-weight-bold text-primary" @click="ctxMenuFollow()">Follow</div>
<div class="list-group-item rounded cursor-pointer" @click="ctxMenuGoToPost()">Go to post</div> <div class="list-group-item rounded cursor-pointer" @click="ctxMenuGoToPost()">Go to post</div>
<div v-if="ctxMenuStatus && ctxMenuStatus.local == true" class="list-group-item rounded cursor-pointer" @click="ctxMenuEmbed()">Embed</div> <div v-if="ctxMenuStatus && ctxMenuStatus.local == true && !ctxMenuStatus.in_reply_to_id" class="list-group-item rounded cursor-pointer" @click="ctxMenuEmbed()">Embed</div>
<!-- <div class="list-group-item rounded cursor-pointer" @click="ctxMenuShare()">Share</div> --> <!-- <div class="list-group-item rounded cursor-pointer" @click="ctxMenuShare()">Share</div> -->
<div class="list-group-item rounded cursor-pointer" @click="ctxMenuCopyLink()">Copy Link</div> <div class="list-group-item rounded cursor-pointer" @click="ctxMenuCopyLink()">Copy Link</div>
<div v-if="profile && profile.is_admin == true" class="list-group-item rounded cursor-pointer" @click="ctxModMenuShow()">Moderation Tools</div> <div v-if="profile && profile.is_admin == true" class="list-group-item rounded cursor-pointer" @click="ctxModMenuShow()">Moderation Tools</div>
@ -558,6 +558,10 @@
</span> </span>
</div> </div>
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div class="custom-control custom-switch mr-3">
<input type="checkbox" class="custom-control-input" id="replyModalCWSwitch" v-model="replyNsfw">
<label :class="[replyNsfw ? 'custom-control-label font-weight-bold text-dark':'custom-control-label text-lighter']" for="replyModalCWSwitch">Mark as NSFW</label>
</div>
<!-- <select class="custom-select custom-select-sm my-0 mr-2"> <!-- <select class="custom-select custom-select-sm my-0 mr-2">
<option value="public" selected="">Public</option> <option value="public" selected="">Public</option>
<option value="unlisted">Unlisted</option> <option value="unlisted">Unlisted</option>
@ -675,6 +679,7 @@
showReadMore: true, showReadMore: true,
replyStatus: {}, replyStatus: {},
replyText: '', replyText: '',
replyNsfw: false,
emoji: window.App.util.emoji, emoji: window.App.util.emoji,
showHashtagPosts: false, showHashtagPosts: false,
hashtagPosts: [], hashtagPosts: [],
@ -697,6 +702,7 @@
mpPoller: null mpPoller: null
} }
}, },
watch: { watch: {
ctxEmbedShowCaption: function (n,o) { ctxEmbedShowCaption: function (n,o) {
if(n == true) { if(n == true) {
@ -721,6 +727,7 @@
this.ctxEmbedPayload = window.App.util.embed.post(this.ctxMenuStatus.url, this.ctxEmbedShowCaption, this.ctxEmbedShowLikes, mode); this.ctxEmbedPayload = window.App.util.embed.post(this.ctxMenuStatus.url, this.ctxEmbedShowCaption, this.ctxEmbedShowLikes, mode);
} }
}, },
beforeMount() { beforeMount() {
this.fetchProfile(); this.fetchProfile();
this.fetchTimelineApi(); this.fetchTimelineApi();
@ -1072,7 +1079,8 @@
} }
axios.post('/i/comment', { axios.post('/i/comment', {
item: id, item: id,
comment: comment comment: comment,
sensitive: this.replyNsfw
}).then(res => { }).then(res => {
this.replyText = ''; this.replyText = '';
this.replies.unshift(res.data.entity); this.replies.unshift(res.data.entity);
@ -1663,6 +1671,7 @@
}, 500); }, 500);
}, },
}, },
beforeDestroy () { beforeDestroy () {
clearInterval(this.mpInterval); clearInterval(this.mpInterval);
}, },

@ -120,6 +120,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
Route::get('discover', 'InternalApiController@discover'); Route::get('discover', 'InternalApiController@discover');
Route::get('discover/posts', 'InternalApiController@discoverPosts')->middleware('auth:api'); Route::get('discover/posts', 'InternalApiController@discoverPosts')->middleware('auth:api');
Route::get('profile/{username}/status/{postid}', 'PublicApiController@status'); Route::get('profile/{username}/status/{postid}', 'PublicApiController@status');
Route::get('profile/{username}/status/{postid}/state', 'PublicApiController@statusState');
Route::get('comments/{username}/status/{postId}', 'PublicApiController@statusComments'); Route::get('comments/{username}/status/{postId}', 'PublicApiController@statusComments');
Route::get('likes/profile/{username}/status/{id}', 'PublicApiController@statusLikes'); Route::get('likes/profile/{username}/status/{id}', 'PublicApiController@statusLikes');
Route::get('shares/profile/{username}/status/{id}', 'PublicApiController@statusShares'); Route::get('shares/profile/{username}/status/{id}', 'PublicApiController@statusShares');

Loading…
Cancel
Save