mirror of https://github.com/pixelfed/pixelfed
commit
f13ba6d08f
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class AccountInterstitial extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['read_at', 'appeal_requested_at'];
|
||||
|
||||
public const JSON_MESSAGE = 'Please use web browser to proceed.';
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function status()
|
||||
{
|
||||
if($this->item_type != 'App\Status') {
|
||||
return;
|
||||
}
|
||||
return $this->hasOne(Status::class, 'id', 'item_id');
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Status;
|
||||
use App\AccountInterstitial;
|
||||
|
||||
class AccountInterstitialController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
public function get(Request $request)
|
||||
{
|
||||
$interstitial = $request->user()
|
||||
->interstitials()
|
||||
->whereNull('read_at')
|
||||
->first();
|
||||
if(!$interstitial) {
|
||||
$user = $request->user();
|
||||
$user->has_interstitial = false;
|
||||
$user->save();
|
||||
return redirect('/');
|
||||
}
|
||||
$meta = json_decode($interstitial->meta);
|
||||
$view = $interstitial->view;
|
||||
return view($view, compact('interstitial', 'meta'));
|
||||
}
|
||||
|
||||
public function read(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'id' => 'required',
|
||||
'type' => 'required|in:post.cw,post.removed,post.unlist',
|
||||
'action' => 'required|in:appeal,confirm',
|
||||
'appeal_message' => 'nullable|max:500'
|
||||
]);
|
||||
|
||||
$redirect = '/';
|
||||
|
||||
$id = decrypt($request->input('id'));
|
||||
$action = $request->input('action');
|
||||
$user = $request->user();
|
||||
|
||||
$ai = AccountInterstitial::whereUserId($user->id)
|
||||
->whereType($request->input('type'))
|
||||
->findOrFail($id);
|
||||
|
||||
if($action == 'appeal') {
|
||||
$ai->appeal_requested_at = now();
|
||||
$ai->appeal_message = $request->input('appeal_message');
|
||||
}
|
||||
|
||||
$ai->read_at = now();
|
||||
$ai->save();
|
||||
|
||||
$more = AccountInterstitial::whereUserId($user->id)
|
||||
->whereNull('read_at')
|
||||
->exists();
|
||||
|
||||
if(!$more) {
|
||||
$user->has_interstitial = false;
|
||||
$user->save();
|
||||
}
|
||||
|
||||
if(in_array($ai->type, ['post.cw', 'post.unlist'])) {
|
||||
$redirect = Status::findOrFail($ai->item_id)->url();
|
||||
}
|
||||
|
||||
return redirect($redirect);
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Auth;
|
||||
use App\User;
|
||||
|
||||
class AccountInterstitial
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$ar = [
|
||||
'login',
|
||||
'logout',
|
||||
'password*',
|
||||
'loginAs*',
|
||||
'i/warning*',
|
||||
'i/auth/checkpoint',
|
||||
'i/auth/sudo',
|
||||
'site/privacy',
|
||||
'site/terms',
|
||||
'site/kb/community-guidelines',
|
||||
];
|
||||
|
||||
if(Auth::check() && !$request->is($ar)) {
|
||||
if($request->user()->has_interstitial) {
|
||||
if($request->wantsJson()) {
|
||||
$res = ['_refresh'=>true,'error' => 403, 'message' => \App\AccountInterstitial::JSON_MESSAGE];
|
||||
return response()->json($res, 403);
|
||||
} else {
|
||||
return redirect('/i/warning');
|
||||
}
|
||||
} else {
|
||||
return $next($request);
|
||||
}
|
||||
} else {
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Util\Blurhash;
|
||||
|
||||
final class AC {
|
||||
|
||||
public static function encode(array $value, float $max_value): float {
|
||||
$quant_r = static::quantise($value[0] / $max_value);
|
||||
$quant_g = static::quantise($value[1] / $max_value);
|
||||
$quant_b = static::quantise($value[2] / $max_value);
|
||||
return $quant_r * 19 * 19 + $quant_g * 19 + $quant_b;
|
||||
}
|
||||
|
||||
public static function decode(int $value, float $max_value): array {
|
||||
$quant_r = floor($value / (19 * 19));
|
||||
$quant_g = floor($value / 19) % 19;
|
||||
$quant_b = $value % 19;
|
||||
|
||||
return [
|
||||
static::signPow(($quant_r - 9) / 9, 2) * $max_value,
|
||||
static::signPow(($quant_g - 9) / 9, 2) * $max_value,
|
||||
static::signPow(($quant_b - 9) / 9, 2) * $max_value
|
||||
];
|
||||
}
|
||||
|
||||
private static function quantise(float $value): float {
|
||||
return floor(max(0, min(18, floor(static::signPow($value, 0.5) * 9 + 9.5))));
|
||||
}
|
||||
|
||||
private static function signPow(float $base, float $exp): float {
|
||||
$sign = $base <=> 0;
|
||||
return $sign * pow(abs($base), $exp);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Util\Blurhash;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Base83 {
|
||||
private const ALPHABET = [
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
|
||||
'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
|
||||
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'x', 'y', 'z', '#', '$', '%', '*', '+', ',', '-', '.',
|
||||
':', ';', '=', '?', '@', '[', ']', '^', '_', '{', '|', '}', '~'
|
||||
];
|
||||
|
||||
private const BASE = 83;
|
||||
|
||||
public static function encode(int $value, int $length): string {
|
||||
if (floor($value / (self::BASE ** $length)) != 0) {
|
||||
throw new InvalidArgumentException('Specified length is too short to encode given value.');
|
||||
}
|
||||
|
||||
$result = '';
|
||||
for ($i = 1; $i <= $length; $i++) {
|
||||
$digit = floor($value / (self::BASE ** ($length - $i))) % self::BASE;
|
||||
$result .= self::ALPHABET[$digit];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function decode(string $hash): int {
|
||||
$result = 0;
|
||||
foreach (str_split($hash) as $char) {
|
||||
$result = $result * self::BASE + (int) array_search($char, self::ALPHABET, true);
|
||||
}
|
||||
return (int) $result;
|
||||
}
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace App\Util\Blurhash;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Blurhash {
|
||||
|
||||
public static function encode(array $image, int $components_x = 4, int $components_y = 4, bool $linear = false): string {
|
||||
if (($components_x < 1 || $components_x > 9) || ($components_y < 1 || $components_y > 9)) {
|
||||
throw new InvalidArgumentException("x and y component counts must be between 1 and 9 inclusive.");
|
||||
}
|
||||
$height = count($image);
|
||||
$width = count($image[0]);
|
||||
|
||||
$image_linear = $image;
|
||||
if (!$linear) {
|
||||
$image_linear = [];
|
||||
for ($y = 0; $y < $height; $y++) {
|
||||
$line = [];
|
||||
for ($x = 0; $x < $width; $x++) {
|
||||
$pixel = $image[$y][$x];
|
||||
$line[] = [
|
||||
Color::toLinear($pixel[0]),
|
||||
Color::toLinear($pixel[1]),
|
||||
Color::toLinear($pixel[2])
|
||||
];
|
||||
}
|
||||
$image_linear[] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
$components = [];
|
||||
$scale = 1 / ($width * $height);
|
||||
for ($y = 0; $y < $components_y; $y++) {
|
||||
for ($x = 0; $x < $components_x; $x++) {
|
||||
$normalisation = $x == 0 && $y == 0 ? 1 : 2;
|
||||
$r = $g = $b = 0;
|
||||
for ($i = 0; $i < $width; $i++) {
|
||||
for ($j = 0; $j < $height; $j++) {
|
||||
$color = $image_linear[$j][$i];
|
||||
$basis = $normalisation
|
||||
* cos(M_PI * $i * $x / $width)
|
||||
* cos(M_PI * $j * $y / $height);
|
||||
|
||||
$r += $basis * $color[0];
|
||||
$g += $basis * $color[1];
|
||||
$b += $basis * $color[2];
|
||||
}
|
||||
}
|
||||
|
||||
$components[] = [
|
||||
$r * $scale,
|
||||
$g * $scale,
|
||||
$b * $scale
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$dc_value = DC::encode(array_shift($components) ?: []);
|
||||
|
||||
$max_ac_component = 0;
|
||||
foreach ($components as $component) {
|
||||
$component[] = $max_ac_component;
|
||||
$max_ac_component = max ($component);
|
||||
}
|
||||
|
||||
$quant_max_ac_component = (int) max(0, min(82, floor($max_ac_component * 166 - 0.5)));
|
||||
$ac_component_norm_factor = ($quant_max_ac_component + 1) / 166;
|
||||
|
||||
$ac_values = [];
|
||||
foreach ($components as $component) {
|
||||
$ac_values[] = AC::encode($component, $ac_component_norm_factor);
|
||||
}
|
||||
|
||||
$blurhash = Base83::encode($components_x - 1 + ($components_y - 1) * 9, 1);
|
||||
$blurhash .= Base83::encode($quant_max_ac_component, 1);
|
||||
$blurhash .= Base83::encode($dc_value, 4);
|
||||
foreach ($ac_values as $ac_value) {
|
||||
$blurhash .= Base83::encode((int) $ac_value, 2);
|
||||
}
|
||||
|
||||
return $blurhash;
|
||||
}
|
||||
|
||||
public static function decode (string $blurhash, int $width, int $height, float $punch = 1.0, bool $linear = false): array {
|
||||
if (empty($blurhash) || strlen($blurhash) < 6) {
|
||||
throw new InvalidArgumentException("Blurhash string must be at least 6 characters");
|
||||
}
|
||||
|
||||
$size_info = Base83::decode($blurhash[0]);
|
||||
$size_y = floor($size_info / 9) + 1;
|
||||
$size_x = ($size_info % 9) + 1;
|
||||
|
||||
$length = (int) strlen($blurhash);
|
||||
$expected_length = (int) (4 + (2 * $size_y * $size_x));
|
||||
if ($length !== $expected_length) {
|
||||
throw new InvalidArgumentException("Blurhash length mismatch: length is {$length} but it should be {$expected_length}");
|
||||
}
|
||||
|
||||
$colors = [DC::decode(Base83::decode(substr($blurhash, 2, 4)))];
|
||||
|
||||
$quant_max_ac_component = Base83::decode($blurhash[1]);
|
||||
$max_value = ($quant_max_ac_component + 1) / 166;
|
||||
for ($i = 1; $i < $size_x * $size_y; $i++) {
|
||||
$value = Base83::decode(substr($blurhash, 4 + $i * 2, 2));
|
||||
$colors[$i] = AC::decode($value, $max_value * $punch);
|
||||
}
|
||||
|
||||
$pixels = [];
|
||||
for ($y = 0; $y < $height; $y++) {
|
||||
$row = [];
|
||||
for ($x = 0; $x < $width; $x++) {
|
||||
$r = $g = $b = 0;
|
||||
for ($j = 0; $j < $size_y; $j++) {
|
||||
for ($i = 0; $i < $size_x; $i++) {
|
||||
$color = $colors[$i + $j * $size_x];
|
||||
$basis =
|
||||
cos((M_PI * $x * $i) / $width) *
|
||||
cos((M_PI * $y * $j) / $height);
|
||||
|
||||
$r += $color[0] * $basis;
|
||||
$g += $color[1] * $basis;
|
||||
$b += $color[2] * $basis;
|
||||
}
|
||||
}
|
||||
|
||||
$row[] = $linear ? [$r, $g, $b] : [
|
||||
Color::toSRGB($r),
|
||||
Color::toSRGB($g),
|
||||
Color::toSRGB($b)
|
||||
];
|
||||
}
|
||||
$pixels[] = $row;
|
||||
}
|
||||
|
||||
return $pixels;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Util\Blurhash;
|
||||
|
||||
final class Color {
|
||||
public static function toLinear(int $value): float {
|
||||
$value = $value / 255;
|
||||
return ($value <= 0.04045)
|
||||
? $value / 12.92
|
||||
: pow(($value + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
public static function tosRGB(float $value): int {
|
||||
$normalized = max(0, min(1, $value));
|
||||
return ($normalized <= 0.0031308)
|
||||
? (int) round($normalized * 12.92 * 255 + 0.5)
|
||||
: (int) round((1.055 * pow($normalized, 1 / 2.4) - 0.055) * 255 + 0.5);
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Util\Blurhash;
|
||||
|
||||
final class DC {
|
||||
|
||||
public static function encode(array $value): int {
|
||||
$rounded_r = Color::tosRGB($value[0]);
|
||||
$rounded_g = Color::tosRGB($value[1]);
|
||||
$rounded_b = Color::tosRGB($value[2]);
|
||||
return ($rounded_r << 16) + ($rounded_g << 8) + $rounded_b;
|
||||
}
|
||||
|
||||
public static function decode(int $value): array {
|
||||
$r = $value >> 16;
|
||||
$g = ($value >> 8) & 255;
|
||||
$b = $value & 255;
|
||||
return [
|
||||
Color::toLinear($r),
|
||||
Color::toLinear($g),
|
||||
Color::toLinear($b)
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Util\Media;
|
||||
|
||||
use App\Util\Blurhash\Blurhash as BlurhashEngine;
|
||||
use App\Media;
|
||||
|
||||
class Blurhash {
|
||||
|
||||
public static function generate(Media $media)
|
||||
{
|
||||
if(!in_array($media->mime, ['image/png', 'image/jpeg'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$file = storage_path('app/' . $media->thumbnail_path);
|
||||
|
||||
if(!is_file($file)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$image = imagecreatefromstring(file_get_contents($file));
|
||||
$width = imagesx($image);
|
||||
$height = imagesy($image);
|
||||
|
||||
$pixels = [];
|
||||
for ($y = 0; $y < $height; ++$y) {
|
||||
$row = [];
|
||||
for ($x = 0; $x < $width; ++$x) {
|
||||
$index = imagecolorat($image, $x, $y);
|
||||
$colors = imagecolorsforindex($image, $index);
|
||||
|
||||
$row[] = [$colors['red'], $colors['green'], $colors['blue']];
|
||||
}
|
||||
$pixels[] = $row;
|
||||
}
|
||||
|
||||
$components_x = 4;
|
||||
$components_y = 4;
|
||||
$blurhash = BlurhashEngine::encode($pixels, $components_x, $components_y);
|
||||
if(strlen($blurhash) > 191) {
|
||||
return;
|
||||
}
|
||||
return $blurhash;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddIndexesToLikesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('likes', function (Blueprint $table) {
|
||||
$table->index('profile_id', 'likes_profile_id_index');
|
||||
$table->index('status_id', 'likes_status_id_index');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('likes', function (Blueprint $table) {
|
||||
$table->dropIndex('likes_profile_id_index');
|
||||
$table->dropIndex('likes_status_id_index');
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateAccountInterstitialsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('account_interstitials', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedInteger('user_id')->nullable()->index();
|
||||
$table->string('type')->nullable();
|
||||
$table->string('view')->nullable();
|
||||
$table->bigInteger('item_id')->unsigned()->nullable();
|
||||
$table->string('item_type')->nullable();
|
||||
$table->boolean('has_media')->default(false)->nullable();
|
||||
$table->string('blurhash')->nullable();
|
||||
$table->text('message')->nullable();
|
||||
$table->text('violation_header')->nullable();
|
||||
$table->text('violation_body')->nullable();
|
||||
$table->json('meta')->nullable();
|
||||
$table->text('appeal_message')->nullable();
|
||||
$table->timestamp('appeal_requested_at')->nullable()->index();
|
||||
$table->timestamp('appeal_handled_at')->nullable()->index();
|
||||
$table->timestamp('read_at')->nullable()->index();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::table('users', function(Blueprint $table) {
|
||||
$table->boolean('has_interstitial')->default(false)->index();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('account_interstitials');
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('has_interstitial');
|
||||
});
|
||||
}
|
||||
}
|
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([[17],{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([[18],{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]]]);
|
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([[24],{15:function(e,a,o){e.exports=o("YMO/")},"YMO/":function(e,a,o){(function(e){function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],(function(e,a,o){a.isDark=!0,a.cssClass="ace-monokai",a.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {color: #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_punctuation,.ace-monokai .ace_punctuation.ace_tag {color: #fff}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y}",e("../lib/dom").importCssString(a.cssText,a.cssClass)})),ace.require(["ace/theme/monokai"],(function(c){"object"==o(e)&&"object"==o(a)&&e&&(e.exports=c)}))}).call(this,o("YuTi")(e))},YuTi:function(e,a){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}}},[[15,0]]]);
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{15:function(e,a,o){e.exports=o("YMO/")},"YMO/":function(e,a,o){(function(e){function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],(function(e,a,o){a.isDark=!0,a.cssClass="ace-monokai",a.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {color: #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_punctuation,.ace-monokai .ace_punctuation.ace_tag {color: #fff}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y}",e("../lib/dom").importCssString(a.cssText,a.cssClass)})),ace.require(["ace/theme/monokai"],(function(c){"object"==o(e)&&"object"==o(a)&&e&&(e.exports=c)}))}).call(this,o("YuTi")(e))},YuTi:function(e,a){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}}},[[15,0]]]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,32 +1,33 @@
|
||||
{
|
||||
"/js/manifest.js": "/js/manifest.js?id=7db827d654313dce4250",
|
||||
"/js/vendor.js": "/js/vendor.js?id=d6ba75064c2942474259",
|
||||
"/js/vendor.js": "/js/vendor.js?id=b9760eb405c3c32b09cf",
|
||||
"/js/ace.js": "/js/ace.js?id=11e5550a450fece75c33",
|
||||
"/js/activity.js": "/js/activity.js?id=838e242ddbe91e559f00",
|
||||
"/js/app.js": "/js/app.js?id=049fdddbb594117f646e",
|
||||
"/js/activity.js": "/js/activity.js?id=85479715e399b3489d25",
|
||||
"/js/app.js": "/js/app.js?id=1c3620016c676056663c",
|
||||
"/css/app.css": "/css/app.css?id=77729cabd5c8a0ad09b8",
|
||||
"/css/appdark.css": "/css/appdark.css?id=995ec87dd4aff426cd1c",
|
||||
"/css/landing.css": "/css/landing.css?id=3092e86721fa8b922c06",
|
||||
"/css/quill.css": "/css/quill.css?id=e3741782d15a3031f785",
|
||||
"/js/collectioncompose.js": "/js/collectioncompose.js?id=3fd79944492361ec7347",
|
||||
"/js/collections.js": "/js/collections.js?id=38be4150f3d2ebb15f50",
|
||||
"/js/collectioncompose.js": "/js/collectioncompose.js?id=72e8fa48c00604a44eb9",
|
||||
"/js/collections.js": "/js/collections.js?id=915db7c1d080d61edcc9",
|
||||
"/js/components.js": "/js/components.js?id=88296701f1382d285031",
|
||||
"/js/compose.js": "/js/compose.js?id=661030734f9228389822",
|
||||
"/js/compose.js": "/js/compose.js?id=e74fdb55681c6d21f4d5",
|
||||
"/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=6a80114ecc453b2b994a",
|
||||
"/js/discover.js": "/js/discover.js?id=dd07b617f5f5f4714164",
|
||||
"/js/hashtag.js": "/js/hashtag.js?id=eb4ce037114cd78a8678",
|
||||
"/js/direct.js": "/js/direct.js?id=e1e4a830bfedc1870db1",
|
||||
"/js/discover.js": "/js/discover.js?id=87071f23fc6d7118c66a",
|
||||
"/js/hashtag.js": "/js/hashtag.js?id=4ebd78fde7fe65f5772c",
|
||||
"/js/loops.js": "/js/loops.js?id=1dcb3790eb9ea4ea5848",
|
||||
"/js/mode-dot.js": "/js/mode-dot.js?id=d54ad862baf30ee756f8",
|
||||
"/js/profile.js": "/js/profile.js?id=746f776639e98cd4102a",
|
||||
"/js/profile-directory.js": "/js/profile-directory.js?id=3a3be60e979308f9958e",
|
||||
"/js/quill.js": "/js/quill.js?id=e47c5b9f47415104bb6a",
|
||||
"/js/rempos.js": "/js/rempos.js?id=0c655b6b8dca92d06c79",
|
||||
"/js/rempro.js": "/js/rempro.js?id=d26f22f402cd6aab5f20",
|
||||
"/js/search.js": "/js/search.js?id=2af4d1de55be62523b71",
|
||||
"/js/status.js": "/js/status.js?id=142b5d5d938c67abdcf6",
|
||||
"/js/story-compose.js": "/js/story-compose.js?id=6308c4b7cb5baa4517d3",
|
||||
"/js/theme-monokai.js": "/js/theme-monokai.js?id=ece67a5ba28761df4d88",
|
||||
"/js/timeline.js": "/js/timeline.js?id=97f92ccb18f86c57dfad"
|
||||
"/js/memoryprofile.js": "/js/memoryprofile.js?id=828e26d71b4330fedc1b",
|
||||
"/js/mode-dot.js": "/js/mode-dot.js?id=dd9c87024fbaa8e75ac4",
|
||||
"/js/profile.js": "/js/profile.js?id=559d809df9a10adc091a",
|
||||
"/js/profile-directory.js": "/js/profile-directory.js?id=855a548efdf56b8594bf",
|
||||
"/js/quill.js": "/js/quill.js?id=866b31b9b9540305751d",
|
||||
"/js/rempos.js": "/js/rempos.js?id=29dacb6e0ce2c936e5cd",
|
||||
"/js/rempro.js": "/js/rempro.js?id=6e7fc68a65bf82d5aec8",
|
||||
"/js/search.js": "/js/search.js?id=5467143312ebae07695b",
|
||||
"/js/status.js": "/js/status.js?id=70f5597c1069d7ead4bb",
|
||||
"/js/story-compose.js": "/js/story-compose.js?id=13f9606a3c4ce7acf17b",
|
||||
"/js/theme-monokai.js": "/js/theme-monokai.js?id=8842103833ba4861bcfa",
|
||||
"/js/timeline.js": "/js/timeline.js?id=8b144724e85e8bef50bf"
|
||||
}
|
||||
|
@ -0,0 +1,130 @@
|
||||
@extends('layouts.blank')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6 offset-md-3 text-center">
|
||||
<p class="h1 pb-2" style="font-weight: 200">Your Post Contains Sensitive or Offensive Material</p>
|
||||
<p class="lead py-3">We applied a Content Warning to your post because it doesn't follow our <a class="font-weight-bold text-dark" href="{{route('help.community-guidelines')}}">Community Guidelines</a>.</p>
|
||||
<p class="font-weight-bold alert alert-danger text-left">To continue you must click the "I Understand" button or "REQUEST APPEAL" button at the bottom of this page.</p>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3">
|
||||
<hr>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3 mt-3">
|
||||
<p class="h4 font-weight-bold">Post Details</p>
|
||||
@if($interstitial->has_media)
|
||||
<div class="py-4 align-items-center">
|
||||
<div class="d-block text-center text-truncate">
|
||||
@if($interstitial->blurhash)
|
||||
<canvas id="mblur" width="400" height="400" class="rounded shadow"></canvas>
|
||||
@else
|
||||
<img src="/storage/no-preview.png" class="mr-3 img-fluid" alt="No preview available">
|
||||
@endif
|
||||
</div>
|
||||
<div class="mt-2 border rounded p-3">
|
||||
@if($meta->caption)
|
||||
<p class="text-break">
|
||||
Caption: <span class="font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-0">
|
||||
Like Count: <span class="font-weight-bold">{{$meta->likes_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Share Count: <span class="font-weight-bold">{{$meta->reblogs_count}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Timestamp: <span class="font-weight-bold">{{now()->parse($meta->created_at)->format('r')}}</span>
|
||||
</p>
|
||||
<p class="mb-0" style="word-break: break-all !important;">
|
||||
URL: <span class="font-weight-bold text-primary">{{$meta->url}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="py-4 align-items-center">
|
||||
<div class="mt-2 border rounded p-3">
|
||||
@if($meta->caption)
|
||||
<p class="text-break">
|
||||
Comment: <span class="font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-0">
|
||||
Like Count: <span class="font-weight-bold">{{$meta->likes_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Share Count: <span class="font-weight-bold">{{$meta->reblogs_count}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Timestamp: <span class="font-weight-bold">{{now()->parse($meta->created_at)->format('r')}}</span>
|
||||
</p>
|
||||
<p class="mb-0" style="word-break: break-all !important;">
|
||||
URL: <span class="font-weight-bold text-primary">{{$meta->url}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3 my-3">
|
||||
<div class="border rounded p-3 border-primary">
|
||||
<p class="h4 font-weight-bold pt-2 text-primary">Review the Community Guidelines</p>
|
||||
<p class="lead pt-4 text-primary">We want to keep {{config('app.name')}} a safe place for everyone, and we created these <a class="font-weight-bold text-primary" href="{{route('help.community-guidelines')}}">Community Guidelines</a> to support and protect our community.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="appealButton" class="col-12 col-md-6 offset-md-3 mt-3">
|
||||
<button type="button" class="btn btn-outline-primary btn-block font-weight-bold" onclick="requestAppeal()">REQUEST APPEAL</button>
|
||||
</div>
|
||||
<div id="appealForm" class="col-12 col-md-6 offset-md-3 d-none mt-3">
|
||||
<form method="post" action="/i/warning">
|
||||
@csrf
|
||||
<p class="h4 font-weight-bold">Request Appeal</p>
|
||||
<p class="pt-4">
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" rows="4" placeholder="Write your appeal request message here" name="appeal_message"></textarea>
|
||||
</div>
|
||||
</p>
|
||||
{{-- <p class="lead"><span class="font-weight-bold">Learn more</span> about what we remove.</p> --}}
|
||||
<input type="hidden" name="id" value="{{encrypt($interstitial->id)}}">
|
||||
<input type="hidden" name="type" value="{{$interstitial->type}}">
|
||||
<input type="hidden" name="action" value="appeal">
|
||||
<button type="submit" class="btn btn-outline-primary btn-block font-weight-bold">REQUEST APPEAL</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6 offset-md-3 mt-4 mb-4">
|
||||
|
||||
<form method="post" action="/i/warning">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="id" value="{{encrypt($interstitial->id)}}">
|
||||
<input type="hidden" name="type" value="{{$interstitial->type}}">
|
||||
<input type="hidden" name="action" value="confirm">
|
||||
<button type="submit" class="btn btn-primary btn-block font-weight-bold">I Understand</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
function requestAppeal() {
|
||||
$('#appealButton').addClass('d-none');
|
||||
$('#appealForm').removeClass('d-none');
|
||||
}
|
||||
</script>
|
||||
@if($interstitial->blurhash)
|
||||
<script type="text/javascript">
|
||||
const pixels = window.blurhash.decode("{{$interstitial->blurhash}}", 400, 400);
|
||||
const canvas = document.getElementById("mblur");
|
||||
const ctx = canvas.getContext("2d");
|
||||
const imageData = ctx.createImageData(400, 400);
|
||||
imageData.data.set(pixels);
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
</script>
|
||||
@endif
|
||||
@endpush
|
@ -0,0 +1,99 @@
|
||||
@extends('layouts.blank')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6 offset-md-3 text-center">
|
||||
<p class="h1 pb-2" style="font-weight: 200">Your Post Has Been Deleted</p>
|
||||
<p class="lead py-1">We removed your post because it doesn't follow our <a class="font-weight-bold text-dark" href="{{route('help.community-guidelines')}}">Community Guidelines</a>. If you violate our guidelines again, your account may be restricted or disabled.</p>
|
||||
<p class="font-weight-bold alert alert-danger text-left">To continue you must click the "I Understand" button at the bottom of this page.</p>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3">
|
||||
<hr>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3 mt-3">
|
||||
<p class="h4 font-weight-bold">Post Details</p>
|
||||
@if($interstitial->has_media)
|
||||
<div class="py-4 align-items-center">
|
||||
<div class="d-block text-center text-truncate">
|
||||
@if($interstitial->blurhash)
|
||||
<canvas id="mblur" width="400" height="400" class="rounded shadow"></canvas>
|
||||
@else
|
||||
<img src="/storage/no-preview.png" class="mr-3 img-fluid" alt="No preview available">
|
||||
@endif
|
||||
</div>
|
||||
<div class="mt-2 border rounded p-3">
|
||||
@if($meta->caption)
|
||||
<p class="text-break">
|
||||
Caption: <span class="font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-0">
|
||||
Like Count: <span class="font-weight-bold">{{$meta->likes_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Share Count: <span class="font-weight-bold">{{$meta->reblogs_count}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Timestamp: <span class="font-weight-bold">{{now()->parse($meta->created_at)->format('r')}}</span>
|
||||
</p>
|
||||
<p class="mb-0" style="word-break: break-all !important;">
|
||||
URL: <span class="font-weight-bold text-primary">{{$meta->url}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="media py-4 align-items-center">
|
||||
<div class="media-body ml-2">
|
||||
<p class="">
|
||||
Comment: <span class="lead text-break font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
<p class="mb-0 small">
|
||||
Posted on {{$meta->created_at}}
|
||||
</p>
|
||||
<p class="mb-0 font-weight-bold text-primary">
|
||||
{{$meta->url}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3 my-3">
|
||||
<div class="border rounded p-3 border-primary">
|
||||
<p class="h4 font-weight-bold pt-2 text-primary">Review the Community Guidelines</p>
|
||||
<p class="lead pt-4 text-primary">We want to keep {{config('app.name')}} a safe place for everyone, and we created these <a class="font-weight-bold text-primary" href="{{route('help.community-guidelines')}}">Community Guidelines</a> to support and protect our community.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3 mt-4 mb-5">
|
||||
<form method="post" action="/i/warning">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="id" value="{{encrypt($interstitial->id)}}">
|
||||
<input type="hidden" name="type" value="{{$interstitial->type}}">
|
||||
<input type="hidden" name="action" value="confirm">
|
||||
<button type="submit" class="btn btn-primary btn-block font-weight-bold">I Understand</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
function requestAppeal() {
|
||||
$('#appealButton').addClass('d-none');
|
||||
$('#appealForm').removeClass('d-none');
|
||||
}
|
||||
</script>
|
||||
@if($interstitial->blurhash)
|
||||
<script type="text/javascript">
|
||||
const pixels = window.blurhash.decode("{{$interstitial->blurhash}}", 400, 400);
|
||||
const canvas = document.getElementById("mblur");
|
||||
const ctx = canvas.getContext("2d");
|
||||
const imageData = ctx.createImageData(400, 400);
|
||||
imageData.data.set(pixels);
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
</script>
|
||||
@endif
|
||||
@endpush
|
@ -0,0 +1,128 @@
|
||||
@extends('layouts.blank')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6 offset-md-3 text-center">
|
||||
<p class="h1 pb-2" style="font-weight: 200">Your Post Was Unlisted</p>
|
||||
<p class="lead py-3">We removed your post from public timelines because it doesn't follow our <a class="font-weight-bold text-dark" href="{{route('help.community-guidelines')}}">Community Guidelines</a>.</p>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3">
|
||||
<hr>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3">
|
||||
<p class="h4 font-weight-bold">Post Details</p>
|
||||
@if($interstitial->has_media)
|
||||
<div class="py-4 align-items-center">
|
||||
<div class="d-block text-center text-truncate">
|
||||
@if($interstitial->blurhash)
|
||||
<canvas id="mblur" width="400" height="400" class="rounded shadow"></canvas>
|
||||
@else
|
||||
<img src="/storage/no-preview.png" class="mr-3 img-fluid" alt="No preview available">
|
||||
@endif
|
||||
</div>
|
||||
<div class="mt-2 border rounded p-3">
|
||||
@if($meta->caption)
|
||||
<p class="text-break">
|
||||
Caption: <span class="font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-0">
|
||||
Like Count: <span class="font-weight-bold">{{$meta->likes_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Share Count: <span class="font-weight-bold">{{$meta->reblogs_count}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Timestamp: <span class="font-weight-bold">{{now()->parse($meta->created_at)->format('r')}}</span>
|
||||
</p>
|
||||
<p class="mb-0" style="word-break: break-all !important;">
|
||||
URL: <span class="font-weight-bold text-primary">{{$meta->url}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="py-4 align-items-center">
|
||||
<div class="mt-2 border rounded p-3">
|
||||
@if($meta->caption)
|
||||
<p class="text-break">
|
||||
Comment: <span class="font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-0">
|
||||
Like Count: <span class="font-weight-bold">{{$meta->likes_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Share Count: <span class="font-weight-bold">{{$meta->reblogs_count}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Timestamp: <span class="font-weight-bold">{{now()->parse($meta->created_at)->format('r')}}</span>
|
||||
</p>
|
||||
<p class="mb-0" style="word-break: break-all !important;">
|
||||
URL: <span class="font-weight-bold text-primary">{{$meta->url}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3 my-3">
|
||||
<div class="border rounded p-3 border-primary">
|
||||
<p class="h4 font-weight-bold pt-2 text-primary">Review the Community Guidelines</p>
|
||||
<p class="lead pt-4 text-primary">We want to keep {{config('app.name')}} a safe place for everyone, and we created these <a class="font-weight-bold text-primary" href="{{route('help.community-guidelines')}}">Community Guidelines</a> to support and protect our community.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="appealButton" class="col-12 col-md-6 offset-md-3">
|
||||
<button type="button" class="btn btn-outline-primary btn-block font-weight-bold" onclick="requestAppeal()">REQUEST APPEAL</button>
|
||||
</div>
|
||||
<div id="appealForm" class="col-12 col-md-6 offset-md-3 d-none">
|
||||
<form method="post" action="/i/warning">
|
||||
@csrf
|
||||
|
||||
<p class="h4 font-weight-bold">Request Appeal</p>
|
||||
<p class="pt-4">
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" rows="4" placeholder="Write your appeal request message here" name="appeal_message"></textarea>
|
||||
</div>
|
||||
</p>
|
||||
<input type="hidden" name="id" value="{{encrypt($interstitial->id)}}">
|
||||
<input type="hidden" name="type" value="{{$interstitial->type}}">
|
||||
<input type="hidden" name="action" value="appeal">
|
||||
<button type="submit" class="btn btn-outline-primary btn-block font-weight-bold">REQUEST APPEAL</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6 offset-md-3 mt-4 mb-4">
|
||||
<form method="post" action="/i/warning">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="id" value="{{encrypt($interstitial->id)}}">
|
||||
<input type="hidden" name="type" value="{{$interstitial->type}}">
|
||||
<input type="hidden" name="action" value="confirm">
|
||||
<button type="submit" class="btn btn-primary btn-block font-weight-bold">I Understand</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
function requestAppeal() {
|
||||
$('#appealButton').addClass('d-none');
|
||||
$('#appealForm').removeClass('d-none');
|
||||
}
|
||||
</script>
|
||||
@if($interstitial->blurhash)
|
||||
<script type="text/javascript">
|
||||
const pixels = window.blurhash.decode("{{$interstitial->blurhash}}", 400, 400);
|
||||
const canvas = document.getElementById("mblur");
|
||||
const ctx = canvas.getContext("2d");
|
||||
const imageData = ctx.createImageData(400, 400);
|
||||
imageData.data.set(pixels);
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
</script>
|
||||
@endif
|
||||
@endpush
|
@ -0,0 +1,63 @@
|
||||
@extends('admin.partial.template-full')
|
||||
|
||||
@section('section')
|
||||
<div class="title mb-3">
|
||||
<h3 class="font-weight-bold d-inline-block">Appeals</h3>
|
||||
<span class="float-right">
|
||||
</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-3 mb-3">
|
||||
<div class="card border bg-primary text-white rounded-pill shadow">
|
||||
<div class="card-body pl-4 ml-3">
|
||||
<p class="h1 font-weight-bold mb-1" style="font-weight: 700">{{App\AccountInterstitial::whereNull('appeal_handled_at')->whereNotNull('appeal_requested_at')->count()}}</p>
|
||||
<p class="lead mb-0 font-weight-lighter">active appeals</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 card border bg-warning text-dark rounded-pill shadow">
|
||||
<div class="card-body pl-4 ml-3">
|
||||
<p class="h1 font-weight-bold mb-1" style="font-weight: 700">{{App\AccountInterstitial::whereNotNull('appeal_handled_at')->whereNotNull('appeal_requested_at')->count()}}</p>
|
||||
<p class="lead mb-0 font-weight-lighter">closed appeals</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-8 offset-md-1">
|
||||
<ul class="list-group">
|
||||
@if($appeals->count() == 0)
|
||||
<li class="list-group-item text-center py-5">
|
||||
<p class="mb-0 py-5 font-weight-bold">No appeals found!</p>
|
||||
</li>
|
||||
@endif
|
||||
@foreach($appeals as $appeal)
|
||||
<a class="list-group-item text-decoration-none text-dark" href="/i/admin/reports/appeal/{{$appeal->id}}">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex align-items-center">
|
||||
<img src="{{$appeal->has_media ? $appeal->status->thumb(true) : '/storage/no-preview.png'}}" width="64" height="64" class="rounded border">
|
||||
<div class="ml-2">
|
||||
<span class="d-inline-block text-truncate">
|
||||
<p class="mb-0 small font-weight-bold text-primary">{{$appeal->type}}</p>
|
||||
@if($appeal->item_type)
|
||||
<p class="mb-0 font-weight-bold">{{starts_with($appeal->item_type, 'App\\') ? explode('\\',$appeal->item_type)[1] : $appeal->item_type}}</p>
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-block">
|
||||
<p class="mb-0 font-weight-bold">@{{$appeal->user->username}}</p>
|
||||
<p class="mb-0 small text-muted font-weight-bold">{{$appeal->created_at->diffForHumans(null, null, true)}}</p>
|
||||
</div>
|
||||
<div class="d-inline-block">
|
||||
<p class="mb-0 small">
|
||||
<i class="fas fa-chevron-right fa-2x text-lighter"></i>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
@endforeach
|
||||
</ul>
|
||||
<p>{!!$appeals->render()!!}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
@ -0,0 +1,125 @@
|
||||
@extends('admin.partial.template-full')
|
||||
|
||||
@section('section')
|
||||
<div class="d-flex justify-content-between title mb-3">
|
||||
<div>
|
||||
<p class="font-weight-bold h3">Moderation Appeal</p>
|
||||
<p class="text-muted mb-0 lead">From <a href="{{$appeal->user->url()}}" class="text-muted font-weight-bold">@{{$appeal->user->username}}</a> about {{$appeal->appeal_requested_at->diffForHumans()}}.</p>
|
||||
</div>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-8 mt-3">
|
||||
@if($appeal->type == 'post.cw')
|
||||
<div class="card shadow-none border">
|
||||
<div class="card-header bg-light h5 font-weight-bold py-4">Content Warning applied to {{$appeal->has_media ? 'Post' : 'Comment'}}</div>
|
||||
@if($appeal->has_media)
|
||||
<img class="card-img-top border-bottom" src="{{$appeal->status->thumb(true)}}">
|
||||
@endif
|
||||
<div class="card-body">
|
||||
<div class="mt-2 p-3">
|
||||
@if($meta->caption)
|
||||
<p class="text-break">
|
||||
{{$appeal->has_media ? 'Caption' : 'Comment'}}: <span class="font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-0">
|
||||
Like Count: <span class="font-weight-bold">{{$meta->likes_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Share Count: <span class="font-weight-bold">{{$meta->reblogs_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Timestamp: <span class="font-weight-bold">{{now()->parse($meta->created_at)->format('r')}}</span>
|
||||
</p>
|
||||
<p class="" style="word-break: break-all !important;">
|
||||
URL: <span class="font-weight-bold text-primary"><a href="{{$meta->url}}">{{$meta->url}}</a></span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Message: <span class="font-weight-bold">{{$appeal->appeal_message}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@elseif($appeal->type == 'post.unlist')
|
||||
<div class="card shadow-none border">
|
||||
<div class="card-header bg-light h5 font-weight-bold py-4">{{$appeal->has_media ? 'Post' : 'Comment'}} was unlisted from timelines</div>
|
||||
@if($appeal->has_media)
|
||||
<img class="card-img-top border-bottom" src="{{$appeal->status->thumb(true)}}">
|
||||
@endif
|
||||
<div class="card-body">
|
||||
<div class="mt-2 p-3">
|
||||
@if($meta->caption)
|
||||
<p class="text-break">
|
||||
{{$appeal->has_media ? 'Caption' : 'Comment'}}: <span class="font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-0">
|
||||
Like Count: <span class="font-weight-bold">{{$meta->likes_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Share Count: <span class="font-weight-bold">{{$meta->reblogs_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Timestamp: <span class="font-weight-bold">{{now()->parse($meta->created_at)->format('r')}}</span>
|
||||
</p>
|
||||
<p class="" style="word-break: break-all !important;">
|
||||
URL: <span class="font-weight-bold text-primary"><a href="{{$meta->url}}">{{$meta->url}}</a></span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Message: <span class="font-weight-bold">{{$appeal->appeal_message}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-12 col-md-4 mt-3">
|
||||
<form method="post">
|
||||
@csrf
|
||||
<input type="hidden" name="action" value="dismiss">
|
||||
<button type="submit" class="btn btn-primary btn-block font-weight-bold mb-3">Dismiss Appeal Request</button>
|
||||
</form>
|
||||
<button type="button" class="btn btn-light border btn-block font-weight-bold mb-3" onclick="approveWarning()">Approve Appeal</button>
|
||||
<div class="card shadow-none border mt-5">
|
||||
<div class="card-header text-center font-weight-bold bg-light">
|
||||
@{{$appeal->user->username}} stats
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="">
|
||||
Open Appeals: <span class="font-weight-bold">{{App\AccountInterstitial::whereUserId($appeal->user_id)->whereNotNull('appeal_requested_at')->whereNull('appeal_handled_at')->count()}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Total Appeals: <span class="font-weight-bold">{{App\AccountInterstitial::whereUserId($appeal->user_id)->whereNotNull('appeal_requested_at')->count()}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Total Warnings: <span class="font-weight-bold">{{App\AccountInterstitial::whereUserId($appeal->user_id)->count()}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Status Count: <span class="font-weight-bold">{{$appeal->user->statuses()->count()}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Joined: <span class="font-weight-bold">{{$appeal->user->created_at->diffForHumans(null, null, false)}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
function approveWarning() {
|
||||
if(window.confirm('Are you sure you want to approve this appeal?') == true) {
|
||||
axios.post(window.location.href, {
|
||||
action: 'approve'
|
||||
}).then(res => {
|
||||
window.location.href = '/i/admin/reports/appeals';
|
||||
}).catch(err => {
|
||||
swal('Oops!', 'An error occured, please try again later.', 'error');
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@endpush
|
@ -0,0 +1,35 @@
|
||||
@extends('layouts.app',['title' => $profile->username . " on " . config('app.name')])
|
||||
|
||||
@section('content')
|
||||
@if (session('error'))
|
||||
<div class="alert alert-danger text-center font-weight-bold mb-0">
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<memory-profile profile-id="{{$profile->id}}" profile-username="{{$profile->username}}" :profile-settings="{{json_encode($settings)}}" profile-layout="{{$profile->profile_layout ?? 'metro'}}"></memory-profile>
|
||||
@if($profile->website)
|
||||
<a class="d-none" href="{{$profile->website}}" rel="me">{{$profile->website}}</a>
|
||||
@endif
|
||||
|
||||
<noscript>
|
||||
<div class="container">
|
||||
<p class="pt-5 text-center lead">Please enable javascript to view this content.</p>
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('meta')<meta property="og:description" content="{{$profile->bio}}">
|
||||
@if(false == $settings['crawlable'] || $profile->remote_url)
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
@else <meta property="og:image" content="{{$profile->avatarUrl()}}">
|
||||
<link href="{{$profile->permalink('.atom')}}" rel="alternate" title="{{$profile->username}} on Pixelfed" type="application/atom+xml">
|
||||
<link href='{{$profile->permalink()}}' rel='alternate' type='application/activity+json'>
|
||||
@endif
|
||||
@endpush
|
||||
|
||||
@push('scripts')<script type="text/javascript" src="{{ mix('js/memoryprofile.js') }}"></script>
|
||||
<script type="text/javascript" defer>App.boot();</script>
|
||||
|
||||
@endpush
|
Loading…
Reference in New Issue