mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-26 16:23:16 +00:00
commit
d652de6f1b
15 changed files with 427 additions and 159 deletions
|
@ -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,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
BIN
public/js/compose.js
vendored
BIN
public/js/compose.js
vendored
Binary file not shown.
BIN
public/js/memoryprofile.js
vendored
BIN
public/js/memoryprofile.js
vendored
Binary file not shown.
BIN
public/js/profile.js
vendored
BIN
public/js/profile.js
vendored
Binary file not shown.
BIN
public/js/rempos.js
vendored
BIN
public/js/rempos.js
vendored
Binary file not shown.
BIN
public/js/status.js
vendored
BIN
public/js/status.js
vendored
Binary file not shown.
BIN
public/js/timeline.js
vendored
BIN
public/js/timeline.js
vendored
Binary file not shown.
Binary file not shown.
|
@ -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;
|
return;
|
||||||
}
|
}
|
||||||
this.$refs.sharesModal.show();
|
if(this.shares.length) {
|
||||||
|
this.$refs.sharesModal.show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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,21 +1072,6 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
muteProfile() {
|
|
||||||
if($('body').hasClass('loggedIn') == false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
axios.post('/i/mute', {
|
|
||||||
type: 'user',
|
|
||||||
item: this.status.account.id
|
|
||||||
}).then(res => {
|
|
||||||
swal('Success', 'You have successfully muted ' + this.status.account.acct, 'success');
|
|
||||||
}).catch(err => {
|
|
||||||
swal('Error', 'Something went wrong. Please try again later.', 'error');
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
blockProfile() {
|
blockProfile() {
|
||||||
if($('body').hasClass('loggedIn') == false) {
|
if($('body').hasClass('loggedIn') == false) {
|
||||||
return;
|
return;
|
||||||
|
@ -1034,12 +1081,31 @@ export default {
|
||||||
type: 'user',
|
type: 'user',
|
||||||
item: this.status.account.id
|
item: this.status.account.id
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
|
this.$refs.ctxModal.hide();
|
||||||
|
this.relationship.blocking = true;
|
||||||
swal('Success', 'You have successfully blocked ' + this.status.account.acct, 'success');
|
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');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
unblockProfile() {
|
||||||
|
if($('body').hasClass('loggedIn') == false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
axios.post('/i/unblock', {
|
||||||
|
type: 'user',
|
||||||
|
item: this.status.account.id
|
||||||
|
}).then(res => {
|
||||||
|
this.relationship.blocking = false;
|
||||||
|
this.$refs.ctxModal.hide();
|
||||||
|
swal('Success', 'You have successfully unblocked ' + this.status.account.acct, 'success');
|
||||||
|
}).catch(err => {
|
||||||
|
swal('Error', 'Something went wrong. Please try again later.', 'error');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
deletePost(status) {
|
deletePost(status) {
|
||||||
if(!this.ownerOrAdmin()) {
|
if(!this.ownerOrAdmin()) {
|
||||||
return;
|
return;
|
||||||
|
@ -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…
Reference in a new issue