Merge pull request #2659 from pixelfed/staging

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

@ -44,6 +44,7 @@
- Updated FederationController, return 404 for invalid webfinger addresses. Fixes ([#2647](https://github.com/pixelfed/pixelfed/issues/2647)). ([deb6f115](https://github.com/pixelfed/pixelfed/commit/deb6f115))
- Updated InboxPipeline, fail earlier for invalid public keys. Fixes ([#2648](https://github.com/pixelfed/pixelfed/issues/2648)). ([d1c5e9b8](https://github.com/pixelfed/pixelfed/commit/d1c5e9b8))
- Updated Status model, refactor liked and shared methods to fix cache invalidation bug. ([f05c3b66](https://github.com/pixelfed/pixelfed/commit/f05c3b66))
- Updated Timeline component, add inline reports modal. ([e64b4bd3](https://github.com/pixelfed/pixelfed/commit/e64b4bd3))
- ([](https://github.com/pixelfed/pixelfed/commit/))
## [v0.10.10 (2021-01-28)](https://github.com/pixelfed/pixelfed/compare/v0.10.9...v0.10.10)

@ -66,17 +66,14 @@ class AdminController extends Controller
public function reports(Request $request)
{
$this->validate($request, [
'filter' => 'nullable|string|in:all,open,closed'
]);
$filter = $request->input('filter');
$filter = $request->input('filter') == 'closed' ? 'closed' : 'open';
$reports = Report::orderBy('created_at','desc')
->when($filter, function($q, $filter) {
return $filter == 'open' ?
$q->whereNull('admin_seen') :
$q->whereNotNull('admin_seen');
})
->paginate(4);
->paginate(6);
return view('admin.reports.home', compact('reports'));
}

@ -23,7 +23,7 @@ class ReportController extends Controller
$this->validate($request, [
'type' => 'required|alpha_dash',
'id' => 'required|integer|min:1',
]);
]);
return view('report.form');
}
@ -86,11 +86,11 @@ class ReportController extends Controller
public function formStore(Request $request)
{
$this->validate($request, [
'report' => 'required|alpha_dash',
'type' => 'required|alpha_dash',
'id' => 'required|integer|min:1',
'msg' => 'nullable|string|max:150',
]);
'report' => 'required|alpha_dash',
'type' => 'required|alpha_dash',
'id' => 'required|integer|min:1',
'msg' => 'nullable|string|max:150',
]);
$profile = Auth::user()->profile;
$reportType = $request->input('report');
@ -98,10 +98,26 @@ class ReportController extends Controller
$object_type = $request->input('type');
$msg = $request->input('msg');
$object = null;
$types = ['spam', 'sensitive', 'abusive'];
$types = [
// original 3
'spam',
'sensitive',
'abusive',
// new
'underage',
'copyright',
'impersonation',
'scam',
'terrorism'
];
if (!in_array($reportType, $types)) {
return redirect('/timeline')->with('error', 'Invalid report type');
if($request->wantsJson()) {
return abort(400, 'Invalid report type');
} else {
return redirect('/timeline')->with('error', 'Invalid report type');
}
}
switch ($object_type) {
@ -115,16 +131,28 @@ class ReportController extends Controller
break;
default:
return redirect('/timeline')->with('error', 'Invalid report type');
if($request->wantsJson()) {
return abort(400, 'Invalid report type');
} else {
return redirect('/timeline')->with('error', 'Invalid report type');
}
break;
}
if ($exists !== 0) {
return redirect('/timeline')->with('error', 'You have already reported this!');
if($request->wantsJson()) {
return response()->json(200);
} else {
return redirect('/timeline')->with('error', 'You have already reported this!');
}
}
if ($object->profile_id == $profile->id) {
return redirect('/timeline')->with('error', 'You cannot report your own content!');
if($request->wantsJson()) {
return response()->json(200);
} else {
return redirect('/timeline')->with('error', 'You cannot report your own content!');
}
}
$report = new Report();
@ -134,9 +162,13 @@ class ReportController extends Controller
$report->object_type = $object_type;
$report->reported_profile_id = $object->profile_id;
$report->type = $request->input('report');
$report->message = $request->input('msg');
$report->message = e($request->input('msg'));
$report->save();
return redirect('/timeline')->with('status', 'Report successfully sent!');
if($request->wantsJson()) {
return response()->json(200);
} else {
return redirect('/timeline')->with('status', 'Report successfully sent!');
}
}
}

@ -203,6 +203,10 @@ class RestrictedNames
'k',
'key',
'l',
'lang',
'language',
'_lang',
'_language',
'lab',
'labs',
'legal',
@ -255,6 +259,8 @@ class RestrictedNames
'quote',
'query',
'r',
'redirect',
'redirects',
'register',
'registers',
'review',

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

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

File diff suppressed because one or more lines are too long

@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{19:function(t,e,s){t.exports=s("ETg6")},"7wkd":function(t,e,s){"use strict";s.r(e);var o={data:function(){return{loaded:!1,showLoadMore:!0,profiles:[],page:1}},beforeMount:function(){this.fetchData()},methods:{fetchData:function(){var t=this;axios.get("/api/pixelfed/v2/discover/profiles",{params:{page:this.page}}).then((function(e){if(0==e.data.length)return t.showLoadMore=!1,void(t.loaded=!0);t.profiles=e.data,t.showLoadMore=8==t.profiles.length,t.loaded=!0}))},prettyCount:function(t){return App.util.format.count(t)},loadMore:function(){this.loaded=!1,this.page++,this.fetchData()},thumbUrl:function(t){return t.media_attachments[0].url}}},a=s("KHd+"),n=Object(a.a)(o,(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",[s("div",{staticClass:"col-12"},[s("p",{staticClass:"font-weight-bold text-lighter text-uppercase"},[t._v("Profiles Directory")]),t._v(" "),t.loaded?s("div",{},[s("div",{staticClass:"row"},[t._l(t.profiles,(function(e,o){return s("div",{staticClass:"col-12 col-md-6 p-1"},[s("div",{staticClass:"card card-body border shadow-none py-2"},[s("div",{staticClass:"media"},[s("a",{attrs:{href:e.url}},[s("img",{staticClass:"rounded-circle border mr-3",attrs:{src:e.avatar,alt:"...",width:"40px",height:"40px"}})]),t._v(" "),s("div",{staticClass:"media-body"},[s("p",{staticClass:"mt-0 mb-0 font-weight-bold"},[s("a",{staticClass:"text-dark",attrs:{href:e.url}},[t._v(t._s(e.username))])]),t._v(" "),s("p",{staticClass:"mb-1 small text-lighter d-flex justify-content-between font-weight-bold"},[s("span",[s("span",[t._v(t._s(t.prettyCount(e.statuses_count)))]),t._v(" POSTS\n\t\t\t\t\t\t\t\t\t")]),t._v(" "),s("span",[s("span",[t._v(t._s(t.prettyCount(e.followers_count)))]),t._v(" FOLLOWERS\n\t\t\t\t\t\t\t\t\t")])]),t._v(" "),s("p",{staticClass:"mb-1"},t._l(e.posts,(function(e,o){return s("span",{key:"profile_posts_"+o,staticClass:"shadow-sm"},[s("a",{staticClass:"text-decoration-none mr-1",attrs:{href:e.url}},[s("img",{staticClass:"border rounded",attrs:{src:t.thumbUrl(e),width:"62.3px",height:"62.3px"}})])])})),0)])])])])})),t._v(" "),t.showLoadMore?s("div",{staticClass:"col-12"},[s("p",{staticClass:"text-center mb-0 pt-3"},[s("button",{staticClass:"btn btn-outline-secondary btn-sm px-4 py-1 font-weight-bold",on:{click:function(e){return t.loadMore()}}},[t._v("Load More")])])]):t._e()],2)]):s("div",[t._m(0)])])])}),[function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"row"},[e("div",{staticClass:"col-12 d-flex justify-content-center align-items-center"},[e("div",{staticClass:"spinner-border",attrs:{role:"status"}},[e("span",{staticClass:"sr-only"},[this._v("Loading...")])])])])}],!1,null,"7b3eea1c",null);e.default=n.exports},ETg6:function(t,e,s){Vue.component("profile-directory",s("7wkd").default)},"KHd+":function(t,e,s){"use strict";function o(t,e,s,o,a,n,r,i){var c,d="function"==typeof t?t.options:t;if(e&&(d.render=e,d.staticRenderFns=s,d._compiled=!0),o&&(d.functional=!0),n&&(d._scopeId="data-v-"+n),r?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),a&&a.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(r)},d._ssrRegister=c):a&&(c=i?function(){a.call(this,this.$root.$options.shadowRoot)}:a),c)if(d.functional){d._injectStyles=c;var l=d.render;d.render=function(t,e){return c.call(e),l(t,e)}}else{var u=d.beforeCreate;d.beforeCreate=u?[].concat(u,c):[c]}return{exports:t,options:d}}s.d(e,"a",(function(){return o}))}},[[19,0]]]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{19:function(t,e,s){t.exports=s("ETg6")},"7wkd":function(t,e,s){"use strict";s.r(e);var o={data:function(){return{loaded:!1,showLoadMore:!0,profiles:[],page:1}},beforeMount:function(){this.fetchData()},methods:{fetchData:function(){var t=this;axios.get("/api/pixelfed/v2/discover/profiles",{params:{page:this.page}}).then((function(e){if(0==e.data.length)return t.showLoadMore=!1,void(t.loaded=!0);t.profiles=e.data,t.showLoadMore=8==t.profiles.length,t.loaded=!0}))},prettyCount:function(t){return App.util.format.count(t)},loadMore:function(){this.loaded=!1,this.page++,this.fetchData()},thumbUrl:function(t){return t.media_attachments[0].url}}},a=s("KHd+"),n=Object(a.a)(o,(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",[s("div",{staticClass:"col-12"},[s("p",{staticClass:"font-weight-bold text-lighter text-uppercase"},[t._v("Profiles Directory")]),t._v(" "),t.loaded?s("div",{},[s("div",{staticClass:"row"},[t._l(t.profiles,(function(e,o){return s("div",{staticClass:"col-12 col-md-6 p-1"},[s("div",{staticClass:"card card-body border shadow-none py-2"},[s("div",{staticClass:"media"},[s("a",{attrs:{href:e.url}},[s("img",{staticClass:"rounded-circle border mr-3",attrs:{src:e.avatar,alt:"...",width:"40px",height:"40px"}})]),t._v(" "),s("div",{staticClass:"media-body"},[s("p",{staticClass:"mt-0 mb-0 font-weight-bold"},[s("a",{staticClass:"text-dark",attrs:{href:e.url}},[t._v(t._s(e.username))])]),t._v(" "),s("p",{staticClass:"mb-1 small text-lighter d-flex justify-content-between font-weight-bold"},[s("span",[s("span",[t._v(t._s(t.prettyCount(e.statuses_count)))]),t._v(" POSTS\n\t\t\t\t\t\t\t\t\t")]),t._v(" "),s("span",[s("span",[t._v(t._s(t.prettyCount(e.followers_count)))]),t._v(" FOLLOWERS\n\t\t\t\t\t\t\t\t\t")])]),t._v(" "),s("p",{staticClass:"mb-1"},t._l(e.posts,(function(e,o){return s("span",{key:"profile_posts_"+o,staticClass:"shadow-sm"},[s("a",{staticClass:"text-decoration-none mr-1",attrs:{href:e.url}},[s("img",{staticClass:"border rounded",attrs:{src:t.thumbUrl(e),width:"62.3px",height:"62.3px"}})])])})),0)])])])])})),t._v(" "),t.showLoadMore?s("div",{staticClass:"col-12"},[s("p",{staticClass:"text-center mb-0 pt-3"},[s("button",{staticClass:"btn btn-outline-secondary btn-sm px-4 py-1 font-weight-bold",on:{click:function(e){return t.loadMore()}}},[t._v("Load More")])])]):t._e()],2)]):s("div",[t._m(0)])])])}),[function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"row"},[e("div",{staticClass:"col-12 d-flex justify-content-center align-items-center"},[e("div",{staticClass:"spinner-border",attrs:{role:"status"}},[e("span",{staticClass:"sr-only"},[this._v("Loading...")])])])])}],!1,null,"7b3eea1c",null);e.default=n.exports},ETg6:function(t,e,s){Vue.component("profile-directory",s("7wkd").default)},"KHd+":function(t,e,s){"use strict";function o(t,e,s,o,a,n,r,i){var c,d="function"==typeof t?t.options:t;if(e&&(d.render=e,d.staticRenderFns=s,d._compiled=!0),o&&(d.functional=!0),n&&(d._scopeId="data-v-"+n),r?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),a&&a.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(r)},d._ssrRegister=c):a&&(c=i?function(){a.call(this,(d.functional?this.parent:this).$root.$options.shadowRoot)}:a),c)if(d.functional){d._injectStyles=c;var l=d.render;d.render=function(t,e){return c.call(e),l(t,e)}}else{var u=d.beforeCreate;d.beforeCreate=u?[].concat(u,c):[c]}return{exports:t,options:d}}s.d(e,"a",(function(){return o}))}},[[19,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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,34 +1,34 @@
{
"/js/manifest.js": "/js/manifest.js?id=7db827d654313dce4250",
"/js/vendor.js": "/js/vendor.js?id=92f80b74af583bf54d69",
"/js/vendor.js": "/js/vendor.js?id=d93ff5de66e63c8bb611",
"/js/ace.js": "/js/ace.js?id=11e5550a450fece75c33",
"/js/activity.js": "/js/activity.js?id=85479715e399b3489d25",
"/js/activity.js": "/js/activity.js?id=64252d7f9c17e958b8d2",
"/js/app.js": "/js/app.js?id=fdbdd51482b98e1324e8",
"/css/app.css": "/css/app.css?id=d2e819a5e9bd647af865",
"/css/appdark.css": "/css/appdark.css?id=098ef0805c5b9b06ab9e",
"/css/landing.css": "/css/landing.css?id=b1672d4780c21672f548",
"/css/quill.css": "/css/quill.css?id=e3741782d15a3031f785",
"/js/collectioncompose.js": "/js/collectioncompose.js?id=c6a07cb79dd7d6c7b8a0",
"/js/collections.js": "/js/collections.js?id=6f64a9032085ebac28b3",
"/js/components.js": "/js/components.js?id=6a067b7270581d1039cb",
"/js/compose.js": "/js/compose.js?id=4c4a28c5b88cfa2ee625",
"/js/compose-classic.js": "/js/compose-classic.js?id=283f19c895f4118a2a8b",
"/js/developers.js": "/js/developers.js?id=f75deca5ccf47d43eb07",
"/js/direct.js": "/js/direct.js?id=e1e4a830bfedc1870db1",
"/js/discover.js": "/js/discover.js?id=0e6a97dc8171aaee5767",
"/js/hashtag.js": "/js/hashtag.js?id=883e6d2d079b0ea33175",
"/js/loops.js": "/js/loops.js?id=1dcb3790eb9ea4ea5848",
"/js/memoryprofile.js": "/js/memoryprofile.js?id=75ea0503eca4f7ad3642",
"/css/app.css": "/css/app.css?id=9a0aaaef301793358e3a",
"/css/appdark.css": "/css/appdark.css?id=d582a698993f108ec182",
"/css/landing.css": "/css/landing.css?id=135e3d12b7cb15e0228b",
"/css/quill.css": "/css/quill.css?id=711b2150d518816d6112",
"/js/collectioncompose.js": "/js/collectioncompose.js?id=37ac6f2e9cbcd035704f",
"/js/collections.js": "/js/collections.js?id=be6208c4ab7909ad8ebe",
"/js/components.js": "/js/components.js?id=56aa48f8042553148a78",
"/js/compose.js": "/js/compose.js?id=c493ce1400063b8ab861",
"/js/compose-classic.js": "/js/compose-classic.js?id=ee4ad4759a55261c429c",
"/js/developers.js": "/js/developers.js?id=f8efa9cb9101d403d6c2",
"/js/direct.js": "/js/direct.js?id=735c52376bc4f3ec102e",
"/js/discover.js": "/js/discover.js?id=b954935be21c33a6bafa",
"/js/hashtag.js": "/js/hashtag.js?id=2238ded8e17551cea303",
"/js/loops.js": "/js/loops.js?id=4ae79e81965c4fd1ae66",
"/js/memoryprofile.js": "/js/memoryprofile.js?id=1dbacb8b611b63cc22f2",
"/js/mode-dot.js": "/js/mode-dot.js?id=dd9c87024fbaa8e75ac4",
"/js/my2020.js": "/js/my2020.js?id=31aeb1c22e0a5a99b0a8",
"/js/profile.js": "/js/profile.js?id=c787e9f712ca6e9e6a27",
"/js/profile-directory.js": "/js/profile-directory.js?id=2386392b464e9088a859",
"/js/my2020.js": "/js/my2020.js?id=4a9d534053da8e6467c0",
"/js/profile.js": "/js/profile.js?id=ac2fa43d195f02c0225e",
"/js/profile-directory.js": "/js/profile-directory.js?id=e63d5f2c6f2d5710a8bd",
"/js/quill.js": "/js/quill.js?id=4769f11fc9a6c32dde50",
"/js/rempos.js": "/js/rempos.js?id=7bdf1b763726cfd80233",
"/js/rempro.js": "/js/rempro.js?id=38ad09b48b084cd82995",
"/js/search.js": "/js/search.js?id=edd612b83049bf276b19",
"/js/status.js": "/js/status.js?id=0fe4f1dbce69d907d08e",
"/js/story-compose.js": "/js/story-compose.js?id=b31904f8fd5b397f8c54",
"/js/rempos.js": "/js/rempos.js?id=680df036dc36c4c7e3da",
"/js/rempro.js": "/js/rempro.js?id=6cca99808897aaf5acf5",
"/js/search.js": "/js/search.js?id=f4319adfd5750db3be3f",
"/js/status.js": "/js/status.js?id=2336a391ee6dcfb3403a",
"/js/story-compose.js": "/js/story-compose.js?id=99dc1cd352d71e41843d",
"/js/theme-monokai.js": "/js/theme-monokai.js?id=85f0af57479412548223",
"/js/timeline.js": "/js/timeline.js?id=c0d6f37d91cb6e56aa11"
"/js/timeline.js": "/js/timeline.js?id=3f189a30f1c6c99c1c5e"
}

@ -27,8 +27,8 @@ pixelfed.readmore = () => {
el.readmore({
collapsedHeight: 45,
heightMargin: 48,
moreLink: '<a href="#" class="d-block small text-muted text-center">Read more ...</a>',
lessLink: '<a href="#" class="d-block small text-muted text-center">Hide</a>',
moreLink: '<a href="#" class="d-block small font-weight-bold text-dark text-center">Show more</a>',
lessLink: '<a href="#" class="d-block small font-weight-bold text-dark text-center">Show less</a>',
});
});
};

@ -601,17 +601,17 @@
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="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 v-if="user && user.is_admin == true" class="list-group-item rounded cursor-pointer" @click="ctxModMenu()">Moderation Tools</div>
<div v-if="status && user.id != status.account.id && !relationship.blocking && !user.is_admin" class="list-group-item rounded cursor-pointer 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 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 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 text-danger" @click="deletePost(ctxMenuStatus)">Delete</div>
<div class="list-group-item rounded cursor-pointer text-lighter" @click="closeCtxMenu()">Cancel</div>
</div>
</b-modal>

@ -469,221 +469,323 @@
</div>
</div>
</div>
<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="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-primary" @click="ctxMenuFollow()">Follow</div>
<div class="list-group-item rounded cursor-pointer" @click="ctxMenuGoToPost()">Go to post</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="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="ctxMenuStatus && (profile.is_admin || profile.id == ctxMenuStatus.account.id)" class="list-group-item rounded cursor-pointer" @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="moderatePost(ctxMenuStatus, 'unlist')">Unlist from Timelines</div>
<div v-if="ctxMenuStatus.sensitive" class="list-group-item rounded cursor-pointer" @click="moderatePost(ctxMenuStatus, 'remcw')">Remove Content Warning</div>
<div v-else class="list-group-item rounded cursor-pointer" @click="moderatePost(ctxMenuStatus, '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="ctxShareModal"
id="ctx-share-modal"
title="Share"
hide-footer
centered
rounded
size="sm"
body-class="list-group-flush p-0 rounded text-center">
<div class="list-group-item rounded cursor-pointer border-top-0">Email</div>
<div class="list-group-item rounded cursor-pointer">Facebook</div>
<div class="list-group-item rounded cursor-pointer">Mastodon</div>
<div class="list-group-item rounded cursor-pointer">Pinterest</div>
<div class="list-group-item rounded cursor-pointer">Pixelfed</div>
<div class="list-group-item rounded cursor-pointer">Twitter</div>
<div class="list-group-item rounded cursor-pointer">VK</div>
<div class="list-group-item rounded cursor-pointer text-lighter" @click="closeCtxShareMenu()">Cancel</div>
</b-modal>
<b-modal ref="ctxEmbedModal"
id="ctx-embed-modal"
hide-header
hide-footer
centered
rounded
size="md"
body-class="p-2 rounded">
<div>
<div class="form-group">
<textarea class="form-control disabled text-monospace" rows="8" style="overflow-y:hidden;border: 1px solid #efefef; font-size: 12px; line-height: 18px; margin: 0 0 7px;resize:none;" v-model="ctxEmbedPayload" disabled=""></textarea>
</div>
<div class="form-group pl-2 d-flex justify-content-center">
<div class="form-check mr-3">
<input class="form-check-input" type="checkbox" v-model="ctxEmbedShowCaption" :disabled="ctxEmbedCompactMode == true">
<label class="form-check-label font-weight-light">
Show Caption
</label>
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="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 class="list-group-item rounded cursor-pointer" @click="ctxMenuGoToPost()">View Post</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="ctxMenuCopyLink()">Copy Link</div> -->
<div class="list-group-item rounded cursor-pointer" @click="ctxMenuShare()">Share</div>
<div v-if="ctxMenuStatus && profile && profile.is_admin == true" class="list-group-item rounded cursor-pointer" @click="ctxModMenuShow()">Moderation Tools</div>
<div v-if="ctxMenuStatus && ctxMenuStatus.account.id != profile.id" class="list-group-item rounded cursor-pointer text-danger" @click="ctxMenuReportPost()">Report</div>
<div v-if="ctxMenuStatus && (profile.is_admin || profile.id == ctxMenuStatus.account.id)" class="list-group-item rounded cursor-pointer text-danger" @click="deletePost(ctxMenuStatus)">Delete</div>
<div class="list-group-item rounded cursor-pointer text-lighter" @click="closeCtxMenu()">Cancel</div>
</div>
<div class="form-check mr-3">
<input class="form-check-input" type="checkbox" v-model="ctxEmbedShowLikes" :disabled="ctxEmbedCompactMode == true">
<label class="form-check-label font-weight-light">
Show Likes
</label>
</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">
<p class="py-2 px-3 mb-0">
<div class="text-center font-weight-bold text-danger">Moderation Tools</div>
<div class="small text-center text-muted">Select one of the following options</div>
</p>
<div class="list-group-item rounded cursor-pointer" @click="moderatePost(ctxMenuStatus, 'unlist')">Unlist from Timelines</div>
<div v-if="ctxMenuStatus.sensitive" class="list-group-item rounded cursor-pointer" @click="moderatePost(ctxMenuStatus, 'remcw')">Remove Content Warning</div>
<div v-else class="list-group-item rounded cursor-pointer" @click="moderatePost(ctxMenuStatus, 'addcw')">Add Content Warning</div>
<!-- <div class="list-group-item rounded cursor-pointer" @click="ctxModOtherMenuShow()">Other</div> -->
<div class="list-group-item rounded cursor-pointer text-lighter" @click="ctxModMenuClose()">Cancel</div>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" v-model="ctxEmbedCompactMode">
<label class="form-check-label font-weight-light">
Compact Mode
</label>
</b-modal>
<b-modal ref="ctxModOtherModal"
id="ctx-mod-other-modal"
hide-header
hide-footer
centered
rounded
size="sm"
body-class="list-group-flush p-0 rounded">
<div class="list-group text-center">
<p class="py-2 px-3 mb-0">
<div class="text-center font-weight-bold text-danger">Moderation Tools</div>
<div class="small text-center text-muted">Select one of the following options</div>
</p>
<div class="list-group-item rounded cursor-pointer font-weight-bold" @click="confirmModal()">Unlist Posts</div>
<div class="list-group-item rounded cursor-pointer font-weight-bold" @click="confirmModal()">Moderation Log</div>
<div class="list-group-item rounded cursor-pointer text-lighter" @click="ctxModOtherMenuClose()">Cancel</div>
</div>
</div>
<hr>
<button :class="copiedEmbed ? 'btn btn-primary btn-block btn-sm py-1 font-weight-bold disabed': 'btn btn-primary btn-block btn-sm py-1 font-weight-bold'" @click="ctxCopyEmbed" :disabled="copiedEmbed">{{copiedEmbed ? 'Embed Code Copied!' : 'Copy Embed Code'}}</button>
<p class="mb-0 px-2 small text-muted">By using this embed, you agree to our <a href="/site/terms">Terms of Use</a></p>
</div>
</b-modal>
<b-modal
id="lightbox"
ref="lightboxModal"
hide-header
hide-footer
centered
size="lg"
body-class="p-0"
>
<div v-if="lightboxMedia" :class="lightboxMedia.filter_class" class="w-100 h-100">
<img :src="lightboxMedia.url" style="max-height: 100%; max-width: 100%" alt="lightbox media">
</div>
</b-modal>
<b-modal ref="replyModal"
id="ctx-reply-modal"
hide-footer
centered
rounded
:title-html="replyStatus.account ? 'Reply to <span class=text-dark>' + replyStatus.account.username + '</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">
</b-modal>
<b-modal ref="ctxShareModal"
id="ctx-share-modal"
title="Share"
hide-footer
hide-header
centered
rounded
size="sm"
body-class="list-group-flush p-0 rounded text-center">
<div class="list-group-item rounded cursor-pointer" @click="ctxMenuCopyLink()">Copy Link</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 border-top-0">Email</div>
<div class="list-group-item rounded cursor-pointer">Facebook</div>
<div class="list-group-item rounded cursor-pointer">Mastodon</div>
<div class="list-group-item rounded cursor-pointer">Pinterest</div>
<div class="list-group-item rounded cursor-pointer">Pixelfed</div>
<div class="list-group-item rounded cursor-pointer">Twitter</div>
<div class="list-group-item rounded cursor-pointer">VK</div> -->
<div class="list-group-item rounded cursor-pointer text-lighter" @click="closeCtxShareMenu()">Cancel</div>
</b-modal>
<b-modal ref="ctxEmbedModal"
id="ctx-embed-modal"
hide-header
hide-footer
centered
rounded
size="md"
body-class="p-2 rounded">
<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 class="form-group">
<textarea class="form-control disabled text-monospace" rows="8" style="overflow-y:hidden;border: 1px solid #efefef; font-size: 12px; line-height: 18px; margin: 0 0 7px;resize:none;" v-model="ctxEmbedPayload" disabled=""></textarea>
</div>
<div class="form-group pl-2 d-flex justify-content-center">
<div class="form-check mr-3">
<input class="form-check-input" type="checkbox" v-model="ctxEmbedShowCaption" :disabled="ctxEmbedCompactMode == true">
<label class="form-check-label font-weight-light">
Show Caption
</label>
</div>
<div class="form-check mr-3">
<input class="form-check-input" type="checkbox" v-model="ctxEmbedShowLikes" :disabled="ctxEmbedCompactMode == true">
<label class="form-check-label font-weight-light">
Show Likes
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" v-model="ctxEmbedCompactMode">
<label class="form-check-label font-weight-light">
Compact Mode
</label>
</div>
</div>
<hr>
<button :class="copiedEmbed ? 'btn btn-primary btn-block btn-sm py-1 font-weight-bold disabed': 'btn btn-primary btn-block btn-sm py-1 font-weight-bold'" @click="ctxCopyEmbed" :disabled="copiedEmbed">{{copiedEmbed ? 'Embed Code Copied!' : 'Copy Embed Code'}}</button>
<p class="mb-0 px-2 small text-muted">By using this embed, you agree to our <a href="/site/terms">Terms of Use</a></p>
</div>
</b-modal>
<b-modal ref="ctxReport"
id="ctx-report"
hide-header
hide-footer
centered
rounded
size="sm"
body-class="list-group-flush p-0 rounded">
<p class="py-2 px-3 mb-0">
<div class="text-center font-weight-bold text-danger">Report</div>
<div class="small text-center text-muted">Select one of the following options</div>
</p>
<div class="list-group text-center">
<div class="list-group-item rounded cursor-pointer font-weight-bold" @click="sendReport('spam')">Spam</div>
<div class="list-group-item rounded cursor-pointer font-weight-bold" @click="sendReport('sensitive')">Sensitive Content</div>
<div class="list-group-item rounded cursor-pointer font-weight-bold" @click="sendReport('abusive')">Abusive or Harmful</div>
<div class="list-group-item rounded cursor-pointer font-weight-bold" @click="openCtxReportOtherMenu()">Other</div>
<!-- <div class="list-group-item rounded cursor-pointer" @click="ctxReportMenuGoBack()">Go Back</div> -->
<div class="list-group-item rounded cursor-pointer text-lighter" @click="ctxReportMenuGoBack()">Cancel</div>
</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="replyNsfw">
<label :class="[replyNsfw ? 'custom-control-label font-weight-bold text-dark':'custom-control-label text-lighter']" for="replyModalCWSwitch">Mark as NSFW</label>
</b-modal>
<b-modal ref="ctxReportOther"
id="ctx-report-other"
hide-header
hide-footer
centered
rounded
size="sm"
body-class="list-group-flush p-0 rounded">
<p class="py-2 px-3 mb-0">
<div class="text-center font-weight-bold text-danger">Report</div>
<div class="small text-center text-muted">Select one of the following options</div>
</p>
<div class="list-group text-center">
<div class="list-group-item rounded cursor-pointer font-weight-bold" @click="sendReport('underage')">Underage Account</div>
<div class="list-group-item rounded cursor-pointer font-weight-bold" @click="sendReport('copyright')">Copyright Infringement</div>
<div class="list-group-item rounded cursor-pointer font-weight-bold" @click="sendReport('impersonation')">Impersonation</div>
<div class="list-group-item rounded cursor-pointer font-weight-bold" @click="sendReport('scam')">Scam or Fraud</div>
<!-- <div class="list-group-item rounded cursor-pointer font-weight-bold" @click="sendReport('terrorism')">Terrorism Related</div> -->
<!-- <div class="list-group-item rounded cursor-pointer font-weight-bold" @click="sendReport('other')">Other or Not listed</div> -->
<!-- <div class="list-group-item rounded cursor-pointer" @click="ctxReportOtherMenuGoBack()">Go Back</div> -->
<div class="list-group-item rounded cursor-pointer text-lighter" @click="ctxReportOtherMenuGoBack()">Cancel</div>
</div>
</b-modal>
<b-modal ref="ctxConfirm"
id="ctx-confirm"
hide-header
hide-footer
centered
rounded
size="sm"
body-class="list-group-flush p-0 rounded">
<div class="d-flex align-items-center justify-content-center py-3">
<div>{{ this.confirmModalTitle }}</div>
</div>
<div class="d-flex border-top btn-group btn-group-block rounded-0" role="group">
<button type="button" class="btn btn-outline-lighter border-left-0 border-top-0 border-bottom-0 border-right py-2" style="color: rgb(0,122,255) !important;" @click.prevent="confirmModalCancel()">Cancel</button>
<button type="button" class="btn btn-outline-lighter border-0" style="color: rgb(0,122,255) !important;" @click.prevent="confirmModalConfirm()">Confirm</button>
</div>
</b-modal>
<b-modal ref="lightboxModal"
id="lightbox"
hide-header
hide-footer
centered
size="lg"
body-class="p-0"
>
<div v-if="lightboxMedia" :class="lightboxMedia.filter_class" class="w-100 h-100">
<img :src="lightboxMedia.url" style="max-height: 100%; max-width: 100%" alt="lightbox media">
</div>
</b-modal>
<b-modal ref="replyModal"
id="ctx-reply-modal"
hide-footer
centered
rounded
:title-html="replyStatus.account ? 'Reply to <span class=text-dark>' + replyStatus.account.username + '</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>
<!-- <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="commentSubmit(status, $event)" :disabled="replyText.length == 0">
{{replySending == true ? 'POSTING' : 'POST'}}
</button>
<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="replyNsfw">
<label :class="[replyNsfw ? 'custom-control-label font-weight-bold text-dark':'custom-control-label text-lighter']" for="replyModalCWSwitch">Mark as NSFW</label>
</div>
<button class="btn btn-primary btn-sm py-2 px-4 lead text-uppercase font-weight-bold" v-on:click.prevent="commentSubmit(status, $event)" :disabled="replyText.length == 0">
{{replySending == true ? 'POSTING' : 'POST'}}
</button>
</div>
</div>
</div>
</div>
</b-modal>
</b-modal>
<b-modal ref="ctxStatusModal"
id="ctx-status-modal"
hide-header
hide-footer
centered
rounded
size="xl"
body-class="list-group-flush p-0 m-0 rounded">
<!-- <post-component
v-if="ctxMenuStatus"
:status-template="ctxMenuStatus.pf_type"
:status-id="ctxMenuStatus.id"
:status-username="ctxMenuStatus.account.username"
:status-url="ctxMenuStatus.url"
:status-profile-url="ctxMenuStatus.account.url"
:status-avatar="ctxMenuStatus.account.avatar"
:status-profile-id="ctxMenuStatus.account.id"
profile-layout="metro">
</post-component> -->
</b-modal>
</div>
</template>
<style type="text/css" scoped>
.postPresenterContainer {
display: flex;
align-items: center;
background: #fff;
}
.word-break {
word-break: break-all;
}
.small .custom-control-label {
padding-top: 3px;
}
.reply-btn {
position: absolute;
bottom: 12px;
right: 20px;
width: 60px;
text-align: center;
border-radius: 0 3px 3px 0;
}
.emoji-reactions .nav-item {
font-size: 1.2rem;
padding: 9px;
cursor: pointer;
}
.emoji-reactions::-webkit-scrollbar {
width: 0px;
height: 0px;
background: transparent;
}
.reply-btn[disabled] {
opacity: .3;
color: #3897f0;
}
.has-story {
width: 64px;
height: 64px;
border-radius: 50%;
padding: 2px;
background: radial-gradient(ellipse at 70% 70%, #ee583f 8%, #d92d77 42%, #bd3381 58%);
}
.has-story img {
width: 60px;
height: 60px;
border-radius: 50%;
padding: 3px;
background: #fff;
}
.has-story.has-story-sm {
width: 32px;
height: 32px;
border-radius: 50%;
padding: 2px;
background: radial-gradient(ellipse at 70% 70%, #ee583f 8%, #d92d77 42%, #bd3381 58%);
}
.has-story.has-story-sm img {
width: 28px;
height: 28px;
border-radius: 50%;
padding: 3px;
background: #fff;
}
#ctx-reply-modal .form-control:focus {
border: none;
outline: 0;
box-shadow: none;
}
.postPresenterContainer {
display: flex;
align-items: center;
background: #fff;
}
.word-break {
word-break: break-all;
}
.small .custom-control-label {
padding-top: 3px;
}
.reply-btn {
position: absolute;
bottom: 12px;
right: 20px;
width: 60px;
text-align: center;
border-radius: 0 3px 3px 0;
}
.emoji-reactions .nav-item {
font-size: 1.2rem;
padding: 9px;
cursor: pointer;
}
.emoji-reactions::-webkit-scrollbar {
width: 0px;
height: 0px;
background: transparent;
}
.reply-btn[disabled] {
opacity: .3;
color: #3897f0;
}
.has-story {
width: 64px;
height: 64px;
border-radius: 50%;
padding: 2px;
background: radial-gradient(ellipse at 70% 70%, #ee583f 8%, #d92d77 42%, #bd3381 58%);
}
.has-story img {
width: 60px;
height: 60px;
border-radius: 50%;
padding: 3px;
background: #fff;
}
.has-story.has-story-sm {
width: 32px;
height: 32px;
border-radius: 50%;
padding: 2px;
background: radial-gradient(ellipse at 70% 70%, #ee583f 8%, #d92d77 42%, #bd3381 58%);
}
.has-story.has-story-sm img {
width: 28px;
height: 28px;
border-radius: 50%;
padding: 3px;
background: #fff;
}
#ctx-reply-modal .form-control:focus {
border: none;
outline: 0;
box-shadow: none;
}
</style>
<script type="text/javascript">
@ -739,7 +841,10 @@ body-class="p-2 rounded">
mpData: false,
mpInterval: 15000,
mpEnabled: false,
mpPoller: null
mpPoller: null,
confirmModalTitle: 'Are you sure?',
confirmModalIdentifer: null,
confirmModalType: false
}
},
@ -1090,7 +1195,7 @@ body-class="p-2 rounded">
this.feed = this.feed.filter(s => {
return s.id != status.id;
});
this.$refs.ctxModal.hide();
this.closeModals();
}).catch(err => {
swal('Error', 'Something went wrong. Please try again later.', 'error');
});
@ -1473,12 +1578,15 @@ body-class="p-2 rounded">
this.ctxMenuStatus = false;
this.ctxMenuRelationship = false;
this.$refs.ctxModal.hide();
this.$refs.ctxReport.hide();
this.$refs.ctxReportOther.hide();
this.closeModals();
},
ctxMenuCopyLink() {
let status = this.ctxMenuStatus;
navigator.clipboard.writeText(status.url);
this.closeCtxMenu();
this.closeModals();
return;
},
@ -1521,11 +1629,14 @@ body-class="p-2 rounded">
},
ctxMenuReportPost() {
window.location.href = '/i/report?type=post&id=' + this.ctxMenuStatus.id;
this.$refs.ctxModal.hide();
this.$refs.ctxReport.show();
return;
// window.location.href = '/i/report?type=post&id=' + this.ctxMenuStatus.id;
},
ctxMenuEmbed() {
this.$refs.ctxModal.hide();
this.closeModals();
this.$refs.ctxEmbedModal.show();
},
@ -1551,14 +1662,25 @@ body-class="p-2 rounded">
this.$refs.ctxModal.hide();
this.$refs.ctxModModal.show();
},
ctxModOtherMenuShow() {
this.$refs.ctxModal.hide();
this.$refs.ctxModModal.hide();
this.$refs.ctxModOtherModal.show();
},
ctxModMenu() {
this.$refs.ctxModal.hide();
},
ctxModMenuClose() {
this.$refs.ctxModal.hide();
this.$refs.ctxModModal.hide();
this.closeModals();
this.$refs.ctxModal.show();
},
ctxModOtherMenuClose() {
this.closeModals();
this.$refs.ctxModModal.show();
},
formatCount(count) {
@ -1703,11 +1825,113 @@ body-class="p-2 rounded">
labelRedirect(type) {
let url = '/i/redirect?url=' + encodeURI(this.config.features.label.covid.url);
window.location.href = url;
},
openCtxReportOtherMenu() {
let s = this.ctxMenuStatus;
this.closeCtxMenu();
this.ctxMenuStatus = s;
this.$refs.ctxReportOther.show();
},
ctxReportMenuGoBack() {
this.$refs.ctxReportOther.hide();
this.$refs.ctxReport.hide();
this.$refs.ctxModal.show();
},
ctxReportOtherMenuGoBack() {
this.$refs.ctxReportOther.hide();
this.$refs.ctxModal.hide();
this.$refs.ctxReport.show();
},
sendReport(type) {
let id = this.ctxMenuStatus.id;
swal({
'title': 'Confirm Report',
'text': 'Are you sure you want to report this post?',
'icon': 'warning',
'buttons': true,
'dangerMode': true
}).then((res) => {
if(res) {
axios.post('/i/report/', {
'report': type,
'type': 'post',
'id': id,
}).then(res => {
this.closeCtxMenu();
swal('Report Sent!', 'We have successfully received your report.', 'success');
}).catch(err => {
swal('Oops!', 'There was an issue reporting this post.', 'error');
})
} else {
this.closeCtxMenu();
}
});
},
closeModals() {
this.$refs.ctxModal.hide();
this.$refs.ctxModModal.hide();
this.$refs.ctxModOtherModal.hide();
this.$refs.ctxShareModal.hide();
this.$refs.ctxEmbedModal.hide();
this.$refs.ctxReport.hide();
this.$refs.ctxReportOther.hide();
this.$refs.ctxConfirm.hide();
this.$refs.lightboxModal.hide();
this.$refs.replyModal.hide();
this.$refs.ctxStatusModal.hide();
},
openCtxStatusModal() {
this.closeModals();
this.$refs.ctxStatusModal.show();
},
openConfirmModal() {
this.closeModals();
this.$refs.ctxConfirm.show();
},
closeConfirmModal() {
this.closeModals();
this.confirmModalTitle = 'Are you sure?';
this.confirmModalType = false;
this.confirmModalIdentifer = null;
},
confirmModalConfirm() {
switch(this.confirmModalType) {
case 'post.delete':
axios.post('/i/delete', {
type: 'status',
item: this.confirmModalIdentifer
}).then(res => {
this.feed = this.feed.filter(s => {
return s.id != this.confirmModalIdentifer;
});
this.closeConfirmModal();
}).catch(err => {
this.closeConfirmModal();
swal('Error', 'Something went wrong. Please try again later.', 'error');
});
break;
}
this.closeConfirmModal();
},
confirmModalCancel() {
this.closeConfirmModal();
}
},
beforeDestroy () {
clearInterval(this.mpInterval);
},
}
}
</script>

@ -1,108 +1,90 @@
@extends('admin.partial.template-full')
@section('section')
<div class="title mb-3">
<h3 class="font-weight-bold d-inline-block">Reports</h3>
<span class="float-right">
<a class="btn btn-{{request()->input('filter')=='all'||request()->input('filter')==null?'primary':'light'}} btn-sm font-weight-bold" href="{{route('admin.reports')}}">
ALL
</a>
<a class="btn btn-{{request()->input('filter')=='open'?'primary':'light'}} btn-sm font-weight-bold" href="{{route('admin.reports',['filter'=>'open', 'page' => request()->input('page') ?? 1])}}">
OPEN
</a>
<a class="btn btn-{{request()->input('filter')=='closed'?'primary':'light'}} btn-sm mr-3 font-weight-bold" href="{{route('admin.reports',['filter'=>'closed', 'page' => request()->input('page') ?? 1])}}">
CLOSED
</a>
</span>
</div>
@php($ai = App\AccountInterstitial::whereNotNull('appeal_requested_at')->whereNull('appeal_handled_at')->count())
@php($spam = App\AccountInterstitial::whereType('post.autospam')->whereNull('appeal_handled_at')->count())
@if($ai || $spam)
<div class="mb-4">
<a class="btn btn-outline-primary px-5 py-3 mr-3" href="/i/admin/reports/appeals">
<p class="font-weight-bold h4 mb-0">{{$ai}}</p>
Appeal {{$ai == 1 ? 'Request' : 'Requests'}}
</a>
<a class="btn btn-outline-primary px-5 py-3" href="/i/admin/reports/autospam">
<p class="font-weight-bold h4 mb-0">{{$spam}}</p>
Flagged {{$ai == 1 ? 'Post' : 'Posts'}}
</a>
</div>
@endif
@if($reports->count())
<div class="card shadow-none border">
<div class="list-group list-group-flush">
@foreach($reports as $report)
<div class="list-group-item {{$report->admin_seen ? 'bg-light' : 'bg-white'}}">
<div class="p-4">
<div class="media d-flex align-items-center">
<div class="mr-3 border rounded d-flex justify-content-center align-items-center media-avatar">
<span class="text-lighter lead"><i class="fas fa-camera"></i></span>
</div>
<div class="media-body">
<p class="mb-1 small"><span class="font-weight-bold text-uppercase">{{$report->type}}</span></p>
@if($report->reporter && $report->status)
<p class="mb-0 lead"><a class="font-weight-bold text-dark" href="{{$report->reporter->url()}}">{{$report->reporter->username}}</a> reported this <a href="{{$report->status->url()}}" class="font-weight-bold text-dark">post</a></p>
@else
<p class="mb-0 lead">
@if(!$report->reporter)
<span class="font-weight-bold text-dark">Deleted user</span>
@else
<a class="font-weight-bold text-dark" href="{{$report->reporter->url()}}">{{$report->reporter->username}}</a>
@endif
reported this
@if(!$report->status)
<span class="font-weight-bold text-muted">deleted post</span>
@else
<a href="{{$report->status->url()}}" class="font-weight-bold text-dark">post</a>
@endif
<div class="title mb-3 d-flex justify-content-between align-items-center">
<h3 class="font-weight-bold d-inline-block">Reports</h3>
<div class="float-right">
@if(request()->has('filter') && request()->filter == 'closed')
<a class="mr-3 font-weight-light small text-muted" href="{{route('admin.reports')}}">
View Open Reports
</a>
@else
<a class="mr-3 font-weight-light small text-muted" href="{{route('admin.reports',['filter'=>'closed'])}}">
View Closed Reports
</a>
@endif
</div>
</div>
@php($ai = App\AccountInterstitial::whereNotNull('appeal_requested_at')->whereNull('appeal_handled_at')->count())
@php($spam = App\AccountInterstitial::whereType('post.autospam')->whereNull('appeal_handled_at')->count())
@if($ai || $spam)
<div class="mb-4">
<a class="btn btn-outline-primary px-5 py-3 mr-3" href="/i/admin/reports/appeals">
<p class="font-weight-bold h4 mb-0">{{$ai}}</p>
Appeal {{$ai == 1 ? 'Request' : 'Requests'}}
</a>
<a class="btn btn-outline-primary px-5 py-3" href="/i/admin/reports/autospam">
<p class="font-weight-bold h4 mb-0">{{$spam}}</p>
Flagged {{$ai == 1 ? 'Post' : 'Posts'}}
</a>
</div>
@endif
@if($reports->count())
<div class="col-12 col-md-8 offset-md-2">
<div class="card shadow-none border">
<div class="list-group list-group-flush">
@foreach($reports as $report)
<div class="list-group-item p-1 {{$report->admin_seen ? 'bg-light' : 'bg-white'}}">
<div class="p-0">
<div class="media d-flex align-items-center">
<a class="text-decoration-none" href="{{$report->url()}}">
<img src="{{$report->status->media->count() ? $report->status->thumb(true) : '/storage/no-preview.png'}}" width="64" height="64" class="rounded border shadow mr-3" style="object-fit: cover">
</a>
<div class="media-body">
<p class="mb-1 small"><span class="font-weight-bold text-uppercase text-danger">{{$report->type}}</span></p>
@if($report->reporter && $report->status)
<p class="mb-0"><a class="font-weight-bold text-dark" href="{{$report->reporter->url()}}">{{$report->reporter->username}}</a> reported this <a href="{{$report->status->url()}}" class="font-weight-bold text-dark">post</a></p>
@else
<p class="mb-0 lead">
@if(!$report->reporter)
<span class="font-weight-bold text-dark">Deleted user</span>
@else
<a class="font-weight-bold text-dark" href="{{$report->reporter->url()}}">{{$report->reporter->username}}</a>
@endif
reported this
@if(!$report->status)
<span class="font-weight-bold text-muted">deleted post</span>
@else
<a href="{{$report->status->url()}}" class="font-weight-bold text-dark">post</a>
@endif
</p>
</p>
@endif
</div>
<div class="float-right">
{{-- @if($report->admin_seen == null)
<a class="btn btn-outline-primary btn-sm font-weight-bold py-1 px-2 mr-2" href="{{$report->url()}}/action"><i class="fas fa-check"></i></a>
@endif
<a class="btn btn-outline-primary btn-sm font-weight-bold py-1 px-2 mr-2" href="{{$report->url()}}/action"><i class="fas fa-cog"></i></a> --}}
@if($report->status)
<a class="btn btn-primary btn-sm font-weight-bold py-1 px-3" href="{{$report->url()}}">VIEW</a>
@endif
</div>
</div>
</div>
</div>
@endforeach
</div>
</div>
@else
<div class="card shadow-none border">
<div class="card-body">
<p class="mb-0 p-5 text-center font-weight-bold lead">No reports found</p>
</div>
</div>
@endif
@endif
</div>
<div class="float-right">
@if($report->status)
<a class="text-lighter p-2 text-decoration-none" href="{{$report->url()}}">
View <i class="fas fa-chevron-right ml-2"></i>
</a>
@endif
</div>
</div>
</div>
</div>
@endforeach
</div>
</div>
</div>
@else
<div class="card shadow-none border">
<div class="card-body">
<p class="mb-0 p-5 text-center font-weight-bold lead">No reports found</p>
</div>
</div>
@endif
<div class="d-flex justify-content-center mt-5 small">
{{$reports->appends(['layout'=>request()->layout, 'filter' => request()->filter])->links()}}
</div>
<div class="d-flex justify-content-center mt-5 small">
{{$reports->appends(['layout'=>request()->layout, 'filter' => request()->filter])->links()}}
</div>
@endsection
@push('styles')
<style type="text/css">
.custom-control-label:after, .custom-control-label:before {
top: auto;
bottom: auto;
}
.media-avatar {
width:64px;
height:64px;
background:#e9ecef;
}
</style>
@endpush
@push('scripts')
@endpush

@ -1,167 +1,111 @@
@extends('admin.partial.template-full')
@section('section')
<div class="title">
<h3 class="font-weight-bold">Report #<span class="reportid" data-id="{{$report->id}}">{{$report->id}}</span> - <span class="badge badge-danger">{{ucfirst($report->type)}}</span></h3>
</div>
<div class="d-flex justify-content-between title mb-3">
<div>
<p class="font-weight-bold h3">
Report #{{$report->id}} -
<span class="text-danger">{{ucfirst($report->type)}}</span>
</p>
<p class="text-muted mb-0 lead">
Reported <span class="font-weight-bold">{{$report->created_at->diffForHumans()}}</span> by <a href="{{$report->reporter->url()}}" class="text-muted font-weight-bold">&commat;{{$report->reporter->username}}</a>.
</p>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title">Reported: <a href="{{$report->reported()->url()}}">{{$report->reported()->url()}}</a></h5>
<h6 class="card-subtitle mb-2 text-muted">Reported by: <a href="{{$report->reporter->url()}}">{{$report->reporter->username}}</a></h6>
<p class="card-text text-muted">
<span class="font-weight-bold text-dark">Message: </span>
{{$report->message ?? 'No message provided.'}}
</p>
<div class="row">
<div class="col-12 col-md-8 mt-3">
<div class="card shadow-none border">
@if($report->status->media()->count())
<img class="card-img-top border-bottom" src="{{$report->status->thumb(true)}}">
@endif
<div class="card-body">
<div class="mt-2 p-3">
@if($report->status->caption)
<p class="text-break">
{{$report->status->media()->count() ? 'Caption' : 'Comment'}}: <span class="font-weight-bold">{{$report->status->caption}}</span>
</p>
@endif
<p class="mb-0">
Like Count: <span class="font-weight-bold">{{$report->status->likes_count}}</span>
</p>
<p class="mb-0">
Share Count: <span class="font-weight-bold">{{$report->status->reblogs_count}}</span>
</p>
<p class="mb-0">
Timestamp: <span class="font-weight-bold">{{now()->parse($report->status->created_at)->format('r')}}</span>
</p>
<p class="" style="word-break: break-all !important;">
URL: <span class="font-weight-bold text-primary"><a href="{{$report->status->url()}}">{{$report->status->url()}}</a></span>
</p>
</div>
</div>
</div>
</div>
<div class="col-12 col-md-4 mt-3">
<button type="button" class="btn btn-primary btn-block font-weight-bold mb-3 report-action-btn" data-action="cw">Apply Content Warning</button>
<button type="button" class="btn btn-primary btn-block font-weight-bold mb-3 report-action-btn" data-action="unlist">Unlist Post</button>
<button type="button" class="btn btn-light border btn-block font-weight-bold mb-3 report-action-btn" data-action="ignore">Ignore</button>
@if(!$report->admin_seen)
<a href="#" class="card-link report-action-btn font-weight-bold" data-action="ignore">Ignore</a>
{{-- <a href="#" class="card-link font-weight-bold">Request Mod Feedback</a> --}}
<a href="#" class="card-link report-action-btn font-weight-bold" data-action="cw">Add CW</a>
<a href="#" class="card-link report-action-btn font-weight-bold" data-action="unlist">Unlist/Hide</a>
{{-- <a href="#" class="card-link report-action-btn font-weight-bold text-danger" data-action="delete">Delete</a>
<a href="#" class="card-link report-action-btn font-weight-bold text-danger" data-action="shadowban">Shadowban User</a>
<a href="#" class="card-link report-action-btn font-weight-bold text-danger" data-action="ban">Ban User</a> --}}
@else
<p class="font-weight-bold mb-0">Resolved {{$report->admin_seen->diffForHumans()}}</p>
@endif
</div>
</div>
<div class="card shadow-none border mt-5">
<div class="card-header text-center font-weight-bold bg-light">
&commat;{{$report->reportedUser->username}} stats
</div>
<div class="card-body">
<p>
Total Reports: <span class="font-weight-bold text-danger">{{App\Report::whereReportedProfileId($report->reportedUser->id)->count()}}</span>
</p>
<p>
Total Warnings: <span class="font-weight-bold text-danger">{{App\AccountInterstitial::whereUserId($report->reportedUser->user_id)->count()}}</span>
</p>
<p class="">
Status Count: <span class="font-weight-bold">{{$report->reportedUser->status_count}}</span>
</p>
<p class="">
Follower Count: <span class="font-weight-bold">{{$report->reportedUser->followers_count}}</span>
</p>
<p class="mb-0">
Joined: <span class="font-weight-bold">{{$report->reportedUser->created_at->diffForHumans(null, null, false)}}</span>
</p>
</div>
</div>
<div class="accordion mt-3" id="accordianBackground">
<div class="card">
<div class="card-header bg-white" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link font-weight-bold text-dark" type="button" data-toggle="collapse" data-target="#background" aria-expanded="true" aria-controls="background">
Background
</button>
</h5>
</div>
<div id="background" class="collapse show" aria-labelledby="headingOne">
<div class="card-body">
<div class="row">
<div class="col-12 col-md-6">
<div class="card">
<div class="card-header bg-white font-weight-bold">
Reporter
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">Joined <span class="font-weight-bold">{{$report->reporter->created_at->diffForHumans()}}</span></li>
<li class="list-group-item">Total Reports: <span class="font-weight-bold">{{App\Report::whereProfileId($report->reporter->id)->count()}}</span></li>
<li class="list-group-item">Total Reported: <span class="font-weight-bold">{{App\Report::whereReportedProfileId($report->reporter->id)->count()}}</span></li>
</ul>
</div>
</div>
<div class="col-12 col-md-6">
<div class="card">
<div class="card-header bg-white font-weight-bold">
Reported
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">Joined <span class="font-weight-bold">{{$report->reportedUser->created_at->diffForHumans()}}</span></li>
<li class="list-group-item">Total Reports: <span class="font-weight-bold">{{App\Report::whereProfileId($report->reportedUser->id)->count()}}</span></li>
<li class="list-group-item">Total Reported: <span class="font-weight-bold">{{App\Report::whereReportedProfileId($report->reportedUser->id)->count()}}</span></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card shadow-none border mt-5">
<div class="card-header text-center font-weight-bold bg-light">
&commat;{{$report->reporter->username}} stats
</div>
<div class="card-body">
<p class="">
Status Count: <span class="font-weight-bold">{{$report->reporter->status_count}}</span>
</p>
<p class="">
Follower Count: <span class="font-weight-bold">{{$report->reporter->followers_count}}</span>
</p>
<p class="mb-0">
Joined: <span class="font-weight-bold">{{$report->reporter->created_at->diffForHumans(null, null, false)}}</span>
</p>
</div>
</div>
{{-- <div class="accordion mt-3" id="accordianLog">
<div class="card">
<div class="card-header bg-white" id="headingTwo">
<h5 class="mb-0">
<button class="btn btn-link font-weight-bold text-dark" type="button" data-toggle="collapse" data-target="#log" aria-expanded="true" aria-controls="log">
Activity Log
</button>
</h5>
</div>
<div id="log" class="collapse show" aria-labelledby="headingTwo">
<div class="card-body" style="max-height: 200px;overflow-y: scroll;">
<div class="my-3 border-left-primary">
<p class="pl-2"><a href="#">admin</a> ignored this report. <span class="float-right pl-2 small font-weight-bold">2m</span></p>
</div>
<div class="my-3 border-left-primary">
<p class="pl-2"><a href="#">admin</a> ignored this report. <span class="float-right pl-2 small font-weight-bold">2m</span></p>
</div>
<div class="my-3 border-left-primary">
<p class="pl-2"><a href="#">admin</a> ignored this report. <span class="float-right pl-2 small font-weight-bold">2m</span></p>
</div>
</div>
</div>
</div>
</div> --}}
{{-- <div class="accordion mt-3" id="accordianComments">
<div class="card">
<div class="card-header bg-white" id="headingThree">
<h5 class="mb-0">
<button class="btn btn-link font-weight-bold text-dark" type="button" data-toggle="collapse" data-target="#comments" aria-expanded="true" aria-controls="comments">
Comments
</button>
</h5>
</div>
<div id="comments" class="collapse show" aria-labelledby="headingThree">
<div class="card-body" style="max-height: 400px; overflow-y: scroll;">
<div class="report-comment-wrapper">
<div class="my-3 report-comment">
<div class="card bg-primary text-white">
<div class="card-body">
<a href="#" class="text-white font-weight-bold">[username]</a>: {{str_limit('Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod.', 150)}} <span class="float-right small p-2">2m</span>
</div>
</div>
</div>
<div class="my-3 report-comment">
<div class="card bg-light">
<div class="card-body">
<a href="#" class="font-weight-bold">me</a>: {{str_limit('Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod.', 150)}} <span class="float-right small p-2">2m</span>
</div>
</div>
</div>
<div class="my-3 report-comment">
<div class="card bg-light">
<div class="card-body">
<a href="#" class="font-weight-bold">me</a>: {{str_limit('Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod.', 150)}} <span class="float-right small p-2">2m</span>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer">
<form>
@csrf
<input type="hidden" name="report_id" value="{{$report->id}}">
<input type="text" class="form-control" name="comment" placeholder="Add a comment here" autocomplete="off">
</form>
</div>
</div>
</div>
</div> --}}
</div>
</div>
@endsection
@push('scripts')
<script type="text/javascript">
$(document).on('click', '.report-action-btn', function(e) {
e.preventDefault();
let el = $(this);
let action = el.data('action');
console.log(action);
axios.post(window.location.href, {
'action': action
})
.then(function(res) {
swal('Success', 'Issue updated successfully!', 'success');
window.location.href = window.location.href;
}).catch(function(res) {
swal('Error', res.data.msg, 'error');
});
})
$(document).on('click', '.report-action-btn', function(e) {
e.preventDefault();
let el = $(this);
let action = el.data('action');
axios.post(window.location.href, {
'action': action
})
.then(function(res) {
swal('Success', 'Issue updated successfully!', 'success');
window.location.href = '/i/admin/reports';
}).catch(function(res) {
swal('Error', res.data.msg, 'error');
});
})
</script>
@endpush

@ -2,7 +2,7 @@
use Illuminate\Http\Request;
$middleware = ['auth:api','twofactor','validemail','throttle:60,1','interstitial'];
$middleware = ['auth:api','twofactor','validemail','interstitial'];
Route::post('/f/inbox', 'FederationController@sharedInbox');
Route::post('/users/{username}/inbox', 'FederationController@userInbox');

Loading…
Cancel
Save