mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-10 00:34:50 +00:00
Merge branch 'frontend-ui-refactor' into patch-20
This commit is contained in:
commit
b44ff216d0
53 changed files with 1479 additions and 125 deletions
|
@ -3,8 +3,16 @@
|
|||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Avatar extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
}
|
||||
|
|
15
app/EmailVerification.php
Normal file
15
app/EmailVerification.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class EmailVerification extends Model
|
||||
{
|
||||
public function url()
|
||||
{
|
||||
$base = config('app.url');
|
||||
$path = '/i/confirm-email/' . $this->user_token . '/' . $this->random_token;
|
||||
return "{$base}{$path}";
|
||||
}
|
||||
}
|
|
@ -3,8 +3,10 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Auth, Cache, Redis;
|
||||
use App\{Notification, Profile, User};
|
||||
use Carbon\Carbon;
|
||||
use App\Mail\ConfirmEmail;
|
||||
use Auth, DB, Cache, Mail, Redis;
|
||||
use App\{EmailVerification, Notification, Profile, User};
|
||||
|
||||
class AccountController extends Controller
|
||||
{
|
||||
|
@ -15,13 +17,60 @@ class AccountController extends Controller
|
|||
|
||||
public function notifications(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'page' => 'nullable|min:1|max:3'
|
||||
]);
|
||||
$profile = Auth::user()->profile;
|
||||
//$notifications = $this->fetchNotifications($profile->id);
|
||||
$timeago = Carbon::now()->subMonths(6);
|
||||
$notifications = Notification::whereProfileId($profile->id)
|
||||
->orderBy('id','desc')->take(30)->simplePaginate();
|
||||
->whereDate('created_at', '>', $timeago)
|
||||
->orderBy('id','desc')
|
||||
->take(30)
|
||||
->simplePaginate();
|
||||
|
||||
return view('account.activity', compact('profile', 'notifications'));
|
||||
}
|
||||
|
||||
public function verifyEmail(Request $request)
|
||||
{
|
||||
return view('account.verify_email');
|
||||
}
|
||||
|
||||
public function sendVerifyEmail(Request $request)
|
||||
{
|
||||
if(EmailVerification::whereUserId(Auth::id())->count() !== 0) {
|
||||
return redirect()->back()->with('status', 'A verification email has already been sent! Please check your email.');
|
||||
}
|
||||
|
||||
$user = User::whereNull('email_verified_at')->find(Auth::id());
|
||||
$utoken = hash('sha512', $user->id);
|
||||
$rtoken = str_random(40);
|
||||
|
||||
$verify = new EmailVerification;
|
||||
$verify->user_id = $user->id;
|
||||
$verify->email = $user->email;
|
||||
$verify->user_token = $utoken;
|
||||
$verify->random_token = $rtoken;
|
||||
$verify->save();
|
||||
|
||||
Mail::to($user->email)->send(new ConfirmEmail($verify));
|
||||
|
||||
return redirect()->back()->with('status', 'Email verification email sent!');
|
||||
}
|
||||
|
||||
public function confirmVerifyEmail(Request $request, $userToken, $randomToken)
|
||||
{
|
||||
$verify = EmailVerification::where(DB::raw('BINARY user_token'), $userToken)
|
||||
->where(DB::raw('BINARY random_token'), $randomToken)
|
||||
->firstOrFail();
|
||||
if(Auth::id() === $verify->user_id) {
|
||||
$user = User::find(Auth::id());
|
||||
$user->email_verified_at = Carbon::now();
|
||||
$user->save();
|
||||
return redirect('/timeline');
|
||||
}
|
||||
}
|
||||
|
||||
public function fetchNotifications($id)
|
||||
{
|
||||
$key = config('cache.prefix') . ":user.{$id}.notifications";
|
||||
|
|
|
@ -34,8 +34,8 @@ class CommentController extends Controller
|
|||
|
||||
$reply = new Status();
|
||||
$reply->profile_id = $profile->id;
|
||||
$reply->caption = $comment;
|
||||
$reply->rendered = e($comment);
|
||||
$reply->caption = e(strip_tags($comment));
|
||||
$reply->rendered = $comment;
|
||||
$reply->in_reply_to_id = $status->id;
|
||||
$reply->in_reply_to_profile_id = $status->profile_id;
|
||||
$reply->save();
|
||||
|
|
|
@ -32,6 +32,7 @@ class ProfileController extends Controller
|
|||
// TODO: refactor this mess
|
||||
$owner = Auth::check() && Auth::id() === $user->user_id;
|
||||
$is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false;
|
||||
$is_admin = is_null($user->domain) ? $user->user->is_admin : false;
|
||||
$timeline = $user->statuses()
|
||||
->whereHas('media')
|
||||
->whereNull('in_reply_to_id')
|
||||
|
@ -39,7 +40,7 @@ class ProfileController extends Controller
|
|||
->withCount(['comments', 'likes'])
|
||||
->simplePaginate(21);
|
||||
|
||||
return view('profile.show', compact('user', 'owner', 'is_following', 'timeline'));
|
||||
return view('profile.show', compact('user', 'owner', 'is_following', 'is_admin', 'timeline'));
|
||||
}
|
||||
|
||||
public function showActivityPub(Request $request, $user)
|
||||
|
@ -66,7 +67,8 @@ class ProfileController extends Controller
|
|||
$owner = Auth::check() && Auth::id() === $user->user_id;
|
||||
$is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false;
|
||||
$followers = $profile->followers()->orderBy('created_at','desc')->simplePaginate(12);
|
||||
return view('profile.followers', compact('user', 'profile', 'followers', 'owner', 'is_following'));
|
||||
$is_admin = is_null($user->domain) ? $user->user->is_admin : false;
|
||||
return view('profile.followers', compact('user', 'profile', 'followers', 'owner', 'is_following', 'is_admin'));
|
||||
}
|
||||
|
||||
public function following(Request $request, $username)
|
||||
|
@ -77,7 +79,8 @@ class ProfileController extends Controller
|
|||
$owner = Auth::check() && Auth::id() === $user->user_id;
|
||||
$is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false;
|
||||
$following = $profile->following()->orderBy('created_at','desc')->simplePaginate(12);
|
||||
return view('profile.following', compact('user', 'profile', 'following', 'owner', 'is_following'));
|
||||
$is_admin = is_null($user->domain) ? $user->user->is_admin : false;
|
||||
return view('profile.following', compact('user', 'profile', 'following', 'owner', 'is_following', 'is_admin'));
|
||||
}
|
||||
|
||||
public function savedBookmarks(Request $request, $username)
|
||||
|
@ -88,7 +91,9 @@ class ProfileController extends Controller
|
|||
$user = Auth::user()->profile;
|
||||
$owner = true;
|
||||
$following = false;
|
||||
$timeline = $user->bookmarks()->orderBy('created_at','desc')->simplePaginate(10);
|
||||
return view('profile.show', compact('user', 'owner', 'following', 'timeline'));
|
||||
$timeline = $user->bookmarks()->withCount(['likes','comments'])->orderBy('created_at','desc')->simplePaginate(10);
|
||||
$is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false;
|
||||
$is_admin = is_null($user->domain) ? $user->user->is_admin : false;
|
||||
return view('profile.show', compact('user', 'owner', 'following', 'timeline', 'is_following', 'is_admin'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers;
|
|||
|
||||
use Auth, Cache;
|
||||
use App\Jobs\StatusPipeline\{NewStatusPipeline, StatusDelete};
|
||||
use App\Jobs\ImageOptimizePipeline\ImageOptimize;
|
||||
use Illuminate\Http\Request;
|
||||
use App\{Media, Profile, Status, User};
|
||||
use Vinkla\Hashids\Facades\Hashids;
|
||||
|
@ -14,7 +15,7 @@ class StatusController extends Controller
|
|||
{
|
||||
$user = Profile::whereUsername($username)->firstOrFail();
|
||||
$status = Status::whereProfileId($user->id)
|
||||
->withCount(['likes', 'comments'])
|
||||
->withCount(['likes', 'comments', 'media'])
|
||||
->findOrFail($id);
|
||||
if(!$status->media_path && $status->in_reply_to_id) {
|
||||
return redirect($status->url());
|
||||
|
@ -32,32 +33,51 @@ class StatusController extends Controller
|
|||
$user = Auth::user();
|
||||
|
||||
$this->validate($request, [
|
||||
'photo' => 'required|mimes:jpeg,png,bmp,gif|max:' . config('pixelfed.max_photo_size'),
|
||||
'caption' => 'string|max:' . config('pixelfed.max_caption_length')
|
||||
'photo.*' => 'required|mimes:jpeg,png,bmp,gif|max:' . config('pixelfed.max_photo_size'),
|
||||
'caption' => 'string|max:' . config('pixelfed.max_caption_length'),
|
||||
'cw' => 'nullable|string',
|
||||
'filter_class' => 'nullable|string',
|
||||
'filter_name' => 'nullable|string',
|
||||
]);
|
||||
|
||||
if(count($request->file('photo')) > config('pixelfed.max_album_length')) {
|
||||
return redirect()->back()->with('error', 'Too many files, max limit per post: ' . config('pixelfed.max_album_length'));
|
||||
}
|
||||
|
||||
$cw = $request->filled('cw') && $request->cw == 'on' ? true : false;
|
||||
$monthHash = hash('sha1', date('Y') . date('m'));
|
||||
$userHash = hash('sha1', $user->id . (string) $user->created_at);
|
||||
$storagePath = "public/m/{$monthHash}/{$userHash}";
|
||||
$path = $request->photo->store($storagePath);
|
||||
$profile = $user->profile;
|
||||
|
||||
$status = new Status;
|
||||
$status->profile_id = $profile->id;
|
||||
$status->caption = $request->caption;
|
||||
$status->caption = strip_tags($request->caption);
|
||||
$status->is_nsfw = $cw;
|
||||
|
||||
$status->save();
|
||||
|
||||
$media = new Media;
|
||||
$media->status_id = $status->id;
|
||||
$media->profile_id = $profile->id;
|
||||
$media->user_id = $user->id;
|
||||
$media->media_path = $path;
|
||||
$media->size = $request->file('photo')->getClientSize();
|
||||
$media->mime = $request->file('photo')->getClientMimeType();
|
||||
$media->save();
|
||||
NewStatusPipeline::dispatch($status, $media);
|
||||
$photos = $request->file('photo');
|
||||
$order = 1;
|
||||
foreach ($photos as $k => $v) {
|
||||
$storagePath = "public/m/{$monthHash}/{$userHash}";
|
||||
$path = $v->store($storagePath);
|
||||
$media = new Media;
|
||||
$media->status_id = $status->id;
|
||||
$media->profile_id = $profile->id;
|
||||
$media->user_id = $user->id;
|
||||
$media->media_path = $path;
|
||||
$media->size = $v->getClientSize();
|
||||
$media->mime = $v->getClientMimeType();
|
||||
$media->filter_class = $request->input('filter_class');
|
||||
$media->filter_name = $request->input('filter_name');
|
||||
$media->order = $order;
|
||||
$media->save();
|
||||
ImageOptimize::dispatch($media);
|
||||
$order++;
|
||||
}
|
||||
|
||||
NewStatusPipeline::dispatch($status);
|
||||
|
||||
// TODO: Parse Caption
|
||||
// TODO: Send to subscribers
|
||||
|
||||
return redirect($status->url());
|
||||
|
|
|
@ -60,5 +60,6 @@ class Kernel extends HttpKernel
|
|||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'validemail' => \App\Http\Middleware\EmailVerificationCheck::class,
|
||||
];
|
||||
}
|
||||
|
|
28
app/Http/Middleware/EmailVerificationCheck.php
Normal file
28
app/Http/Middleware/EmailVerificationCheck.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Auth, Closure;
|
||||
|
||||
class EmailVerificationCheck
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if($request->user() &&
|
||||
config('pixelfed.enforce_email_verification') &&
|
||||
is_null($request->user()->email_verified_at) &&
|
||||
!$request->is('i/verify-email') && !$request->is('login') &&
|
||||
!$request->is('i/confirm-email/*')
|
||||
) {
|
||||
return redirect('/i/verify-email');
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
}
|
|
@ -38,7 +38,10 @@ class ImageUpdate implements ShouldQueue
|
|||
$thumb = storage_path('app/'. $media->thumbnail_path);
|
||||
try {
|
||||
ImageOptimizer::optimize($thumb);
|
||||
ImageOptimizer::optimize($path);
|
||||
if($media->mime !== 'image/gif')
|
||||
{
|
||||
ImageOptimizer::optimize($path);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -16,17 +16,15 @@ class NewStatusPipeline implements ShouldQueue
|
|||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected $status;
|
||||
protected $media;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Status $status, $media = false)
|
||||
public function __construct(Status $status)
|
||||
{
|
||||
$this->status = $status;
|
||||
$this->media = $media;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -37,13 +35,10 @@ class NewStatusPipeline implements ShouldQueue
|
|||
public function handle()
|
||||
{
|
||||
$status = $this->status;
|
||||
$media = $this->media;
|
||||
|
||||
StatusEntityLexer::dispatch($status);
|
||||
StatusActivityPubDeliver::dispatch($status);
|
||||
if($media) {
|
||||
ImageOptimize::dispatch($media);
|
||||
}
|
||||
//StatusActivityPubDeliver::dispatch($status);
|
||||
|
||||
Cache::forever('post.' . $status->id, $status);
|
||||
|
||||
$redis = Redis::connection();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace App\Jobs\StatusPipeline;
|
||||
|
||||
use App\{Media, StatusHashtag, Status};
|
||||
use App\{Media, Notification, StatusHashtag, Status};
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
|
@ -58,8 +58,19 @@ class StatusDelete implements ShouldQueue
|
|||
|
||||
}
|
||||
}
|
||||
$comments = Status::where('in_reply_to_id', $status->id)->get();
|
||||
foreach($comments as $comment) {
|
||||
$comment->in_reply_to_id = null;
|
||||
$comment->save();
|
||||
Notification::whereItemType('App\Status')
|
||||
->whereItemId($comment->id)
|
||||
->delete();
|
||||
}
|
||||
|
||||
$status->likes()->delete();
|
||||
Notification::whereItemType('App\Status')
|
||||
->whereItemId($status->id)
|
||||
->delete();
|
||||
StatusHashtag::whereStatusId($status->id)->delete();
|
||||
$status->delete();
|
||||
|
||||
|
|
|
@ -6,21 +6,28 @@ use Cache;
|
|||
use App\{
|
||||
Hashtag,
|
||||
Media,
|
||||
Mention,
|
||||
Profile,
|
||||
Status,
|
||||
StatusHashtag
|
||||
};
|
||||
use App\Util\Lexer\Hashtag as HashtagLexer;
|
||||
use App\Util\Lexer\{Autolink, Extractor};
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use App\Jobs\MentionPipeline\MentionPipeline;
|
||||
|
||||
class StatusEntityLexer implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected $status;
|
||||
protected $entities;
|
||||
protected $autolink;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
|
@ -39,22 +46,40 @@ class StatusEntityLexer implements ShouldQueue
|
|||
public function handle()
|
||||
{
|
||||
$status = $this->status;
|
||||
$this->parseHashtags();
|
||||
$this->parseEntities();
|
||||
}
|
||||
|
||||
public function parseHashtags()
|
||||
public function parseEntities()
|
||||
{
|
||||
$this->extractEntities();
|
||||
}
|
||||
|
||||
public function extractEntities()
|
||||
{
|
||||
$this->entities = Extractor::create()->extract($this->status->caption);
|
||||
$this->autolinkStatus();
|
||||
}
|
||||
|
||||
public function autolinkStatus()
|
||||
{
|
||||
$this->autolink = Autolink::create()->autolink($this->status->caption);
|
||||
$this->storeEntities();
|
||||
}
|
||||
|
||||
public function storeEntities()
|
||||
{
|
||||
$status = $this->status;
|
||||
$text = e($status->caption);
|
||||
$tags = HashtagLexer::getHashtags($text);
|
||||
$rendered = $text;
|
||||
if(count($tags) > 0) {
|
||||
$rendered = HashtagLexer::replaceHashtagsWithLinks($text);
|
||||
}
|
||||
$status->rendered = $rendered;
|
||||
$this->storeHashtags();
|
||||
$this->storeMentions();
|
||||
$status->rendered = $this->autolink;
|
||||
$status->entities = json_encode($this->entities);
|
||||
$status->save();
|
||||
|
||||
Cache::forever('post.' . $status->id, $status);
|
||||
}
|
||||
|
||||
public function storeHashtags()
|
||||
{
|
||||
$tags = array_unique($this->entities['hashtags']);
|
||||
$status = $this->status;
|
||||
|
||||
foreach($tags as $tag) {
|
||||
$slug = str_slug($tag);
|
||||
|
@ -64,11 +89,32 @@ class StatusEntityLexer implements ShouldQueue
|
|||
['slug' => $slug]
|
||||
);
|
||||
|
||||
$stag = new StatusHashtag;
|
||||
$stag->status_id = $status->id;
|
||||
$stag->hashtag_id = $htag->id;
|
||||
$stag->save();
|
||||
StatusHashtag::firstOrCreate(
|
||||
['status_id' => $status->id],
|
||||
['hashtag_id' => $htag->id]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function storeMentions()
|
||||
{
|
||||
$mentions = array_unique($this->entities['mentions']);
|
||||
$status = $this->status;
|
||||
|
||||
foreach($mentions as $mention) {
|
||||
$mentioned = Profile::whereUsername($mention)->first();
|
||||
|
||||
if(empty($mentioned) || !isset($mentioned->id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$m = new Mention;
|
||||
$m->status_id = $status->id;
|
||||
$m->profile_id = $mentioned->id;
|
||||
$m->save();
|
||||
|
||||
MentionPipeline::dispatch($status, $m);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
10
app/Like.php
10
app/Like.php
|
@ -3,9 +3,19 @@
|
|||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Like extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
public function actor()
|
||||
{
|
||||
return $this->belongsTo(Profile::class, 'profile_id', 'id');
|
||||
|
|
34
app/Mail/ConfirmEmail.php
Normal file
34
app/Mail/ConfirmEmail.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\EmailVerification;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class ConfirmEmail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(EmailVerification $verify)
|
||||
{
|
||||
$this->verify = $verify;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
return $this->markdown('emails.confirm_email')->with(['verify'=>$this->verify]);
|
||||
}
|
||||
}
|
|
@ -2,11 +2,21 @@
|
|||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Storage;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Media extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
public function url()
|
||||
{
|
||||
$path = $this->media_path;
|
||||
|
|
|
@ -3,9 +3,18 @@
|
|||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Mention extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
public function profile()
|
||||
{
|
||||
|
@ -14,7 +23,7 @@ class Mention extends Model
|
|||
|
||||
public function status()
|
||||
{
|
||||
return $this->belongsTo(Status::class);
|
||||
return $this->belongsTo(Status::class, 'status_id', 'id');
|
||||
}
|
||||
|
||||
public function toText()
|
||||
|
|
|
@ -3,28 +3,37 @@
|
|||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Notification extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
public function actor()
|
||||
{
|
||||
return $this->belongsTo(Profile::class, 'actor_id', 'id');
|
||||
}
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
public function actor()
|
||||
{
|
||||
return $this->belongsTo(Profile::class, 'actor_id', 'id');
|
||||
}
|
||||
|
||||
public function profile()
|
||||
{
|
||||
return $this->belongsTo(Profile::class, 'profile_id', 'id');
|
||||
}
|
||||
public function profile()
|
||||
{
|
||||
return $this->belongsTo(Profile::class, 'profile_id', 'id');
|
||||
}
|
||||
|
||||
public function item()
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
public function item()
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
public function status()
|
||||
{
|
||||
return $this->belongsTo(Status::class, 'item_id', 'id');
|
||||
}
|
||||
public function status()
|
||||
{
|
||||
return $this->belongsTo(Status::class, 'item_id', 'id');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,15 +5,29 @@ namespace App;
|
|||
use Storage;
|
||||
use App\Util\Lexer\PrettyNumber;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Profile extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
protected $hidden = [
|
||||
'private_key',
|
||||
];
|
||||
|
||||
protected $visible = ['id', 'username', 'name'];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function url($suffix = '')
|
||||
{
|
||||
return url($this->username . $suffix);
|
||||
|
|
|
@ -2,12 +2,21 @@
|
|||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Storage;
|
||||
use Vinkla\Hashids\Facades\Hashids;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Status extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
public function profile()
|
||||
{
|
||||
return $this->belongsTo(Profile::class);
|
||||
|
@ -25,6 +34,9 @@ class Status extends Model
|
|||
|
||||
public function thumb()
|
||||
{
|
||||
if($this->media->count() == 0 || $this->is_nsfw) {
|
||||
return "data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==";
|
||||
}
|
||||
return url(Storage::url($this->firstMedia()->thumbnail_path));
|
||||
}
|
||||
|
||||
|
@ -40,6 +52,11 @@ class Status extends Model
|
|||
return url($path);
|
||||
}
|
||||
|
||||
public function editUrl()
|
||||
{
|
||||
return $this->url() . '/edit';
|
||||
}
|
||||
|
||||
public function mediaUrl()
|
||||
{
|
||||
$media = $this->firstMedia();
|
||||
|
|
10
app/User.php
10
app/User.php
|
@ -3,11 +3,19 @@
|
|||
namespace App;
|
||||
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use Notifiable;
|
||||
use Notifiable, SoftDeletes;
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
|
|
@ -103,6 +103,10 @@ class Image {
|
|||
$ratio = $this->getAspectRatio($file, $thumbnail);
|
||||
$aspect = $ratio['dimensions'];
|
||||
$orientation = $ratio['orientation'];
|
||||
if($media->mime === 'image/gif' && !$thumbnail)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$img = Intervention::make($file)->orientate();
|
||||
|
|
|
@ -96,5 +96,25 @@ return [
|
|||
|
|
||||
*/
|
||||
'max_caption_length' => env('MAX_CAPTION_LENGTH', 150),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Album size limit
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The max number of photos allowed per post.
|
||||
|
|
||||
*/
|
||||
'max_album_length' => env('MAX_ALBUM_LENGTH', 4),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Email Verification
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Require email verification before a new user can do anything.
|
||||
|
|
||||
*/
|
||||
'enforce_email_verification' => env('ENFORCE_EMAIL_VERIFICATION', true),
|
||||
|
||||
];
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddFiltersToMediaTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('media', function (Blueprint $table) {
|
||||
$table->string('filter_name')->nullable()->after('orientation');
|
||||
$table->string('filter_class')->nullable()->after('filter_name');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('media', function (Blueprint $table) {
|
||||
$table->dropColumn('filter_name');
|
||||
$table->dropColumn('filter_class');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddSoftDeletesToModels extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('avatars', function ($table) {
|
||||
$table->softDeletes();
|
||||
});
|
||||
|
||||
Schema::table('likes', function ($table) {
|
||||
$table->softDeletes();
|
||||
});
|
||||
|
||||
Schema::table('media', function ($table) {
|
||||
$table->softDeletes();
|
||||
});
|
||||
|
||||
Schema::table('mentions', function ($table) {
|
||||
$table->softDeletes();
|
||||
});
|
||||
|
||||
Schema::table('notifications', function ($table) {
|
||||
$table->softDeletes();
|
||||
});
|
||||
|
||||
Schema::table('profiles', function ($table) {
|
||||
$table->softDeletes();
|
||||
});
|
||||
|
||||
Schema::table('statuses', function ($table) {
|
||||
$table->softDeletes();
|
||||
});
|
||||
|
||||
Schema::table('users', function ($table) {
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateEmailVerificationsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('email_verifications', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->bigInteger('user_id')->unsigned();
|
||||
$table->string('email')->nullable();
|
||||
$table->string('user_token')->index();
|
||||
$table->string('random_token')->index();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('email_verifications');
|
||||
}
|
||||
}
|
BIN
public/css/app.css
vendored
BIN
public/css/app.css
vendored
Binary file not shown.
BIN
public/js/activity.js
vendored
Normal file
BIN
public/js/activity.js
vendored
Normal file
Binary file not shown.
BIN
public/js/app.js
vendored
BIN
public/js/app.js
vendored
Binary file not shown.
BIN
public/js/timeline.js
vendored
BIN
public/js/timeline.js
vendored
Binary file not shown.
Binary file not shown.
10
resources/assets/js/activity.js
vendored
Normal file
10
resources/assets/js/activity.js
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
$(document).ready(function() {
|
||||
$('.pagination').hide();
|
||||
let elem = document.querySelector('.notification-page .list-group');
|
||||
let infScroll = new InfiniteScroll( elem, {
|
||||
path: '.pagination__next',
|
||||
append: '.notification-page .list-group',
|
||||
status: '.page-load-status',
|
||||
history: true,
|
||||
});
|
||||
});
|
1
resources/assets/js/bootstrap.js
vendored
1
resources/assets/js/bootstrap.js
vendored
|
@ -22,6 +22,7 @@ try {
|
|||
require('./components/commentform');
|
||||
require('./components/searchform');
|
||||
require('./components/bookmarkform');
|
||||
require('./components/statusform');
|
||||
} catch (e) {}
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,6 +14,7 @@ $(document).ready(function() {
|
|||
let commenttext = commentform.val();
|
||||
let item = {item: id, comment: commenttext};
|
||||
|
||||
commentform.prop('disabled', true);
|
||||
axios.post('/i/comment', item)
|
||||
.then(function (res) {
|
||||
|
||||
|
@ -33,6 +34,7 @@ $(document).ready(function() {
|
|||
|
||||
commentform.val('');
|
||||
commentform.blur();
|
||||
commentform.prop('disabled', false);
|
||||
|
||||
})
|
||||
.catch(function (res) {
|
||||
|
|
110
resources/assets/js/components/statusform.js
vendored
Normal file
110
resources/assets/js/components/statusform.js
vendored
Normal file
|
@ -0,0 +1,110 @@
|
|||
$(document).ready(function() {
|
||||
|
||||
$('#statusForm .btn-filter-select').on('click', function(e) {
|
||||
let el = $(this);
|
||||
});
|
||||
|
||||
pixelfed.create = {};
|
||||
pixelfed.filters = {};
|
||||
pixelfed.create.hasGeneratedSelect = false;
|
||||
pixelfed.create.selectedFilter = false;
|
||||
pixelfed.create.currentFilterName = false;
|
||||
pixelfed.create.currentFilterClass = false;
|
||||
|
||||
pixelfed.filters.list = [
|
||||
['1977','filter-1977'],
|
||||
['Aden','filter-aden'],
|
||||
['Amaro','filter-amaro'],
|
||||
['Ashby','filter-ashby'],
|
||||
['Brannan','filter-brannan'],
|
||||
['Brooklyn','filter-brooklyn'],
|
||||
['Charmes','filter-charmes'],
|
||||
['Clarendon','filter-clarendon'],
|
||||
['Crema','filter-crema'],
|
||||
['Dogpatch','filter-dogpatch'],
|
||||
['Earlybird','filter-earlybird'],
|
||||
['Gingham','filter-gingham'],
|
||||
['Ginza','filter-ginza'],
|
||||
['Hefe','filter-hefe'],
|
||||
['Helena','filter-helena'],
|
||||
['Hudson','filter-hudson'],
|
||||
['Inkwell','filter-inkwell'],
|
||||
['Kelvin','filter-kelvin'],
|
||||
['Kuno','filter-juno'],
|
||||
['Lark','filter-lark'],
|
||||
['Lo-Fi','filter-lofi'],
|
||||
['Ludwig','filter-ludwig'],
|
||||
['Maven','filter-maven'],
|
||||
['Mayfair','filter-mayfair'],
|
||||
['Moon','filter-moon'],
|
||||
['Nashville','filter-nashville'],
|
||||
['Perpetua','filter-perpetua'],
|
||||
['Poprocket','filter-poprocket'],
|
||||
['Reyes','filter-reyes'],
|
||||
['Rise','filter-rise'],
|
||||
['Sierra','filter-sierra'],
|
||||
['Skyline','filter-skyline'],
|
||||
['Slumber','filter-slumber'],
|
||||
['Stinson','filter-stinson'],
|
||||
['Sutro','filter-sutro'],
|
||||
['Toaster','filter-toaster'],
|
||||
['Valencia','filter-valencia'],
|
||||
['Vesper','filter-vesper'],
|
||||
['Walden','filter-walden'],
|
||||
['Willow','filter-willow'],
|
||||
['X-Pro II','filter-xpro-ii']
|
||||
];
|
||||
|
||||
function previewImage(input) {
|
||||
if (input.files && input.files[0]) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
$('.filterPreview').attr('src', e.target.result);
|
||||
}
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
}
|
||||
}
|
||||
|
||||
function generateFilterSelect() {
|
||||
let filters = pixelfed.filters.list;
|
||||
for(var i = 0, len = filters.length; i < len; i++) {
|
||||
let filter = filters[i];
|
||||
let name = filter[0];
|
||||
let className = filter[1];
|
||||
let select = $('#filterSelectDropdown');
|
||||
var template = '<option value="' + className + '">' + name + '</option>';
|
||||
select.append(template);
|
||||
}
|
||||
pixelfed.create.hasGeneratedSelect = true;
|
||||
}
|
||||
|
||||
$('#fileInput').on('change', function() {
|
||||
previewImage(this);
|
||||
$('#statusForm .form-filters.d-none').removeClass('d-none');
|
||||
$('#statusForm .form-preview.d-none').removeClass('d-none');
|
||||
$('#statusForm #collapsePreview').collapse('show');
|
||||
if(!pixelfed.create.hasGeneratedSelect) {
|
||||
generateFilterSelect();
|
||||
}
|
||||
});
|
||||
|
||||
$('#filterSelectDropdown').on('change', function() {
|
||||
let el = $(this);
|
||||
let filter = el.val();
|
||||
let oldFilter = pixelfed.create.currentFilterClass;
|
||||
if(filter == 'none') {
|
||||
$('.filterContainer').removeClass(oldFilter);
|
||||
pixelfed.create.currentFilterClass = false;
|
||||
pixelfed.create.currentFilterName = 'None';
|
||||
$('.form-group.form-preview .form-text').text('Current Filter: No filter selected');
|
||||
return;
|
||||
}
|
||||
$('.filterContainer').removeClass(oldFilter).addClass(filter);
|
||||
pixelfed.create.currentFilterClass = filter;
|
||||
pixelfed.create.currentFilterName = el.find(':selected').text();
|
||||
$('.form-group.form-preview .form-text').text('Current Filter: ' + pixelfed.create.currentFilterName);
|
||||
$('input[name=filter_class]').val(pixelfed.create.currentFilterClass);
|
||||
$('input[name=filter_name]').val(pixelfed.create.currentFilterName);
|
||||
});
|
||||
|
||||
});
|
14
resources/assets/sass/_variables.scss
vendored
14
resources/assets/sass/_variables.scss
vendored
|
@ -6,3 +6,17 @@ $body-bg: #f5f8fa;
|
|||
$font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
|
||||
$font-size-base: 0.9rem;
|
||||
$line-height-base: 1.6;
|
||||
|
||||
$font-size-lg: ($font-size-base * 1.25);
|
||||
$font-size-sm: ($font-size-base * .875);
|
||||
$input-height: 2.375rem;
|
||||
$input-height-sm: 1.9375rem;
|
||||
$input-height-lg: 3rem;
|
||||
$input-btn-focus-width: .2rem;
|
||||
$custom-control-indicator-bg: #dee2e6;
|
||||
$custom-control-indicator-disabled-bg: #e9ecef;
|
||||
$custom-control-description-disabled-color: #868e96;
|
||||
$white: white;
|
||||
$theme-colors: (
|
||||
'primary': #08d
|
||||
);
|
6
resources/assets/sass/app.scss
vendored
6
resources/assets/sass/app.scss
vendored
|
@ -11,6 +11,10 @@
|
|||
|
||||
@import "custom";
|
||||
|
||||
@import "components/filters";
|
||||
|
||||
@import "components/typeahead";
|
||||
|
||||
@import "components/notifications";
|
||||
@import "components/notifications";
|
||||
|
||||
@import "components/switch";
|
445
resources/assets/sass/components/filters.scss
vendored
Normal file
445
resources/assets/sass/components/filters.scss
vendored
Normal file
|
@ -0,0 +1,445 @@
|
|||
/*! Instagram.css v0.1.3 | MIT License | github.com/picturepan2/instagram.css */
|
||||
[class*="filter"] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
[class*="filter"]::before {
|
||||
display: block;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.filter-1977 {
|
||||
-webkit-filter: sepia(.5) hue-rotate(-30deg) saturate(1.4);
|
||||
filter: sepia(.5) hue-rotate(-30deg) saturate(1.4);
|
||||
}
|
||||
|
||||
.filter-aden {
|
||||
-webkit-filter: sepia(.2) brightness(1.15) saturate(1.4);
|
||||
filter: sepia(.2) brightness(1.15) saturate(1.4);
|
||||
}
|
||||
|
||||
.filter-aden::before {
|
||||
background: rgba(125, 105, 24, .1);
|
||||
content: "";
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
|
||||
.filter-amaro {
|
||||
-webkit-filter: sepia(.35) contrast(1.1) brightness(1.2) saturate(1.3);
|
||||
filter: sepia(.35) contrast(1.1) brightness(1.2) saturate(1.3);
|
||||
}
|
||||
|
||||
.filter-amaro::before {
|
||||
background: rgba(125, 105, 24, .2);
|
||||
content: "";
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
.filter-ashby {
|
||||
-webkit-filter: sepia(.5) contrast(1.2) saturate(1.8);
|
||||
filter: sepia(.5) contrast(1.2) saturate(1.8);
|
||||
}
|
||||
|
||||
.filter-ashby::before {
|
||||
background: rgba(125, 105, 24, .35);
|
||||
content: "";
|
||||
mix-blend-mode: lighten;
|
||||
}
|
||||
|
||||
.filter-brannan {
|
||||
-webkit-filter: sepia(.4) contrast(1.25) brightness(1.1) saturate(.9) hue-rotate(-2deg);
|
||||
filter: sepia(.4) contrast(1.25) brightness(1.1) saturate(.9) hue-rotate(-2deg);
|
||||
}
|
||||
|
||||
.filter-brooklyn {
|
||||
-webkit-filter: sepia(.25) contrast(1.25) brightness(1.25) hue-rotate(5deg);
|
||||
filter: sepia(.25) contrast(1.25) brightness(1.25) hue-rotate(5deg);
|
||||
}
|
||||
|
||||
.filter-brooklyn::before {
|
||||
background: rgba(127, 187, 227, .2);
|
||||
content: "";
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
.filter-charmes {
|
||||
-webkit-filter: sepia(.25) contrast(1.25) brightness(1.25) saturate(1.35) hue-rotate(-5deg);
|
||||
filter: sepia(.25) contrast(1.25) brightness(1.25) saturate(1.35) hue-rotate(-5deg);
|
||||
}
|
||||
|
||||
.filter-charmes::before {
|
||||
background: rgba(125, 105, 24, .25);
|
||||
content: "";
|
||||
mix-blend-mode: darken;
|
||||
}
|
||||
|
||||
.filter-clarendon {
|
||||
-webkit-filter: sepia(.15) contrast(1.25) brightness(1.25) hue-rotate(5deg);
|
||||
filter: sepia(.15) contrast(1.25) brightness(1.25) hue-rotate(5deg);
|
||||
}
|
||||
|
||||
.filter-clarendon::before {
|
||||
background: rgba(127, 187, 227, .4);
|
||||
content: "";
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
.filter-crema {
|
||||
-webkit-filter: sepia(.5) contrast(1.25) brightness(1.15) saturate(.9) hue-rotate(-2deg);
|
||||
filter: sepia(.5) contrast(1.25) brightness(1.15) saturate(.9) hue-rotate(-2deg);
|
||||
}
|
||||
|
||||
.filter-crema::before {
|
||||
background: rgba(125, 105, 24, .2);
|
||||
content: "";
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
|
||||
.filter-dogpatch {
|
||||
-webkit-filter: sepia(.35) saturate(1.1) contrast(1.5);
|
||||
filter: sepia(.35) saturate(1.1) contrast(1.5);
|
||||
}
|
||||
|
||||
.filter-earlybird {
|
||||
-webkit-filter: sepia(.25) contrast(1.25) brightness(1.15) saturate(.9) hue-rotate(-5deg);
|
||||
filter: sepia(.25) contrast(1.25) brightness(1.15) saturate(.9) hue-rotate(-5deg);
|
||||
}
|
||||
|
||||
.filter-earlybird::before {
|
||||
background: radial-gradient(circle closest-corner, transparent 0, rgba(125, 105, 24, .2) 100%);
|
||||
background: -o-radial-gradient(circle closest-corner, transparent 0, rgba(125, 105, 24, .2) 100%);
|
||||
background: -moz-radial-gradient(circle closest-corner, transparent 0, rgba(125, 105, 24, .2) 100%);
|
||||
background: -webkit-radial-gradient(circle closest-corner, transparent 0, rgba(125, 105, 24, .2) 100%);
|
||||
content: "";
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
|
||||
.filter-gingham {
|
||||
-webkit-filter: contrast(1.1) brightness(1.1);
|
||||
filter: contrast(1.1) brightness(1.1);
|
||||
}
|
||||
|
||||
.filter-gingham::before {
|
||||
background: #e6e6e6;
|
||||
content: "";
|
||||
mix-blend-mode: soft-light;
|
||||
}
|
||||
|
||||
.filter-ginza {
|
||||
-webkit-filter: sepia(.25) contrast(1.15) brightness(1.2) saturate(1.35) hue-rotate(-5deg);
|
||||
filter: sepia(.25) contrast(1.15) brightness(1.2) saturate(1.35) hue-rotate(-5deg);
|
||||
}
|
||||
|
||||
.filter-ginza::before {
|
||||
background: rgba(125, 105, 24, .15);
|
||||
content: "";
|
||||
mix-blend-mode: darken;
|
||||
}
|
||||
|
||||
.filter-hefe {
|
||||
-webkit-filter: sepia(.4) contrast(1.5) brightness(1.2) saturate(1.4) hue-rotate(-10deg);
|
||||
filter: sepia(.4) contrast(1.5) brightness(1.2) saturate(1.4) hue-rotate(-10deg);
|
||||
}
|
||||
|
||||
.filter-hefe::before {
|
||||
background: radial-gradient(circle closest-corner, transparent 0, rgba(0, 0, 0, .25) 100%);
|
||||
background: -o-radial-gradient(circle closest-corner, transparent 0, rgba(0, 0, 0, .25) 100%);
|
||||
background: -moz-radial-gradient(circle closest-corner, transparent 0, rgba(0, 0, 0, .25) 100%);
|
||||
background: -webkit-radial-gradient(circle closest-corner, transparent 0, rgba(0, 0, 0, .25) 100%);
|
||||
content: "";
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
|
||||
.filter-helena {
|
||||
-webkit-filter: sepia(.5) contrast(1.05) brightness(1.05) saturate(1.35);
|
||||
filter: sepia(.5) contrast(1.05) brightness(1.05) saturate(1.35);
|
||||
}
|
||||
|
||||
.filter-helena::before {
|
||||
background: rgba(158, 175, 30, .25);
|
||||
content: "";
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
.filter-hudson {
|
||||
-webkit-filter: sepia(.25) contrast(1.2) brightness(1.2) saturate(1.05) hue-rotate(-15deg);
|
||||
filter: sepia(.25) contrast(1.2) brightness(1.2) saturate(1.05) hue-rotate(-15deg);
|
||||
}
|
||||
|
||||
.filter-hudson::before {
|
||||
background: radial-gradient(circle closest-corner, transparent 25%, rgba(25, 62, 167, .25) 100%);
|
||||
background: -o-radial-gradient(circle closest-corner, transparent 25%, rgba(25, 62, 167, .25) 100%);
|
||||
background: -moz-radial-gradient(circle closest-corner, transparent 25%, rgba(25, 62, 167, .25) 100%);
|
||||
background: -webkit-radial-gradient(circle closest-corner, transparent 25%, rgba(25, 62, 167, .25) 100%);
|
||||
content: "";
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
|
||||
.filter-inkwell {
|
||||
-webkit-filter: brightness(1.25) contrast(.85) grayscale(1);
|
||||
filter: brightness(1.25) contrast(.85) grayscale(1);
|
||||
}
|
||||
|
||||
.filter-juno {
|
||||
-webkit-filter: sepia(.35) contrast(1.15) brightness(1.15) saturate(1.8);
|
||||
filter: sepia(.35) contrast(1.15) brightness(1.15) saturate(1.8);
|
||||
}
|
||||
|
||||
.filter-juno::before {
|
||||
background: rgba(127, 187, 227, .2);
|
||||
content: "";
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
.filter-kelvin {
|
||||
-webkit-filter: sepia(.15) contrast(1.5) brightness(1.1) hue-rotate(-10deg);
|
||||
filter: sepia(.15) contrast(1.5) brightness(1.1) hue-rotate(-10deg);
|
||||
}
|
||||
|
||||
.filter-kelvin::before {
|
||||
background: radial-gradient(circle closest-corner, rgba(128, 78, 15, .25) 0, rgba(128, 78, 15, .5) 100%);
|
||||
background: -o-radial-gradient(circle closest-corner, rgba(128, 78, 15, .25) 0, rgba(128, 78, 15, .5) 100%);
|
||||
background: -moz-radial-gradient(circle closest-corner, rgba(128, 78, 15, .25) 0, rgba(128, 78, 15, .5) 100%);
|
||||
background: -webkit-radial-gradient(circle closest-corner, rgba(128, 78, 15, .25) 0, rgba(128, 78, 15, .5) 100%);
|
||||
content: "";
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
.filter-lark {
|
||||
-webkit-filter: sepia(.25) contrast(1.2) brightness(1.3) saturate(1.25);
|
||||
filter: sepia(.25) contrast(1.2) brightness(1.3) saturate(1.25);
|
||||
}
|
||||
|
||||
.filter-lofi {
|
||||
-webkit-filter: saturate(1.1) contrast(1.5);
|
||||
filter: saturate(1.1) contrast(1.5);
|
||||
}
|
||||
|
||||
.filter-ludwig {
|
||||
-webkit-filter: sepia(.25) contrast(1.05) brightness(1.05) saturate(2);
|
||||
filter: sepia(.25) contrast(1.05) brightness(1.05) saturate(2);
|
||||
}
|
||||
|
||||
.filter-ludwig::before {
|
||||
background: rgba(125, 105, 24, .1);
|
||||
content: "";
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
.filter-maven {
|
||||
-webkit-filter: sepia(.35) contrast(1.05) brightness(1.05) saturate(1.75);
|
||||
filter: sepia(.35) contrast(1.05) brightness(1.05) saturate(1.75);
|
||||
}
|
||||
|
||||
.filter-maven::before {
|
||||
background: rgba(158, 175, 30, .25);
|
||||
content: "";
|
||||
mix-blend-mode: darken;
|
||||
}
|
||||
|
||||
.filter-mayfair {
|
||||
-webkit-filter: contrast(1.1) brightness(1.15) saturate(1.1);
|
||||
filter: contrast(1.1) brightness(1.15) saturate(1.1);
|
||||
}
|
||||
|
||||
.filter-mayfair::before {
|
||||
background: radial-gradient(circle closest-corner, transparent 0, rgba(175, 105, 24, .4) 100%);
|
||||
background: -o-radial-gradient(circle closest-corner, transparent 0, rgba(175, 105, 24, .4) 100%);
|
||||
background: -moz-radial-gradient(circle closest-corner, transparent 0, rgba(175, 105, 24, .4) 100%);
|
||||
background: -webkit-radial-gradient(circle closest-corner, transparent 0, rgba(175, 105, 24, .4) 100%);
|
||||
content: "";
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
|
||||
.filter-moon {
|
||||
-webkit-filter: brightness(1.4) contrast(.95) saturate(0) sepia(.35);
|
||||
filter: brightness(1.4) contrast(.95) saturate(0) sepia(.35);
|
||||
}
|
||||
|
||||
.filter-nashville {
|
||||
-webkit-filter: sepia(.25) contrast(1.5) brightness(.9) hue-rotate(-15deg);
|
||||
filter: sepia(.25) contrast(1.5) brightness(.9) hue-rotate(-15deg);
|
||||
}
|
||||
|
||||
.filter-nashville::before {
|
||||
background: radial-gradient(circle closest-corner, rgba(128, 78, 15, .5) 0, rgba(128, 78, 15, .65) 100%);
|
||||
background: -o-radial-gradient(circle closest-corner, rgba(128, 78, 15, .5) 0, rgba(128, 78, 15, .65) 100%);
|
||||
background: -moz-radial-gradient(circle closest-corner, rgba(128, 78, 15, .5) 0, rgba(128, 78, 15, .65) 100%);
|
||||
background: -webkit-radial-gradient(circle closest-corner, rgba(128, 78, 15, .5) 0, rgba(128, 78, 15, .65) 100%);
|
||||
content: "";
|
||||
mix-blend-mode: screen;
|
||||
}
|
||||
|
||||
.filter-perpetua {
|
||||
-webkit-filter: contrast(1.1) brightness(1.25) saturate(1.1);
|
||||
filter: contrast(1.1) brightness(1.25) saturate(1.1);
|
||||
}
|
||||
|
||||
.filter-perpetua::before {
|
||||
background: linear-gradient(to bottom, rgba(0, 91, 154, .25), rgba(230, 193, 61, .25));
|
||||
background: -o-linear-gradient(top, rgba(0, 91, 154, .25), rgba(230, 193, 61, .25));
|
||||
background: -moz-linear-gradient(top, rgba(0, 91, 154, .25), rgba(230, 193, 61, .25));
|
||||
background: -webkit-linear-gradient(top, rgba(0, 91, 154, .25), rgba(230, 193, 61, .25));
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 91, 154, .25)), to(rgba(230, 193, 61, .25)));
|
||||
content: "";
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
|
||||
.filter-poprocket {
|
||||
-webkit-filter: sepia(.15) brightness(1.2);
|
||||
filter: sepia(.15) brightness(1.2);
|
||||
}
|
||||
|
||||
.filter-poprocket::before {
|
||||
background: radial-gradient(circle closest-corner, rgba(206, 39, 70, .75) 40%, black 80%);
|
||||
background: -o-radial-gradient(circle closest-corner, rgba(206, 39, 70, .75) 40%, black 80%);
|
||||
background: -moz-radial-gradient(circle closest-corner, rgba(206, 39, 70, .75) 40%, black 80%);
|
||||
background: -webkit-radial-gradient(circle closest-corner, rgba(206, 39, 70, .75) 40%, black 80%);
|
||||
content: "";
|
||||
mix-blend-mode: screen;
|
||||
}
|
||||
|
||||
.filter-reyes {
|
||||
-webkit-filter: sepia(.75) contrast(.75) brightness(1.25) saturate(1.4);
|
||||
filter: sepia(.75) contrast(.75) brightness(1.25) saturate(1.4);
|
||||
}
|
||||
|
||||
.filter-rise {
|
||||
-webkit-filter: sepia(.25) contrast(1.25) brightness(1.2) saturate(.9);
|
||||
filter: sepia(.25) contrast(1.25) brightness(1.2) saturate(.9);
|
||||
}
|
||||
|
||||
.filter-rise::before {
|
||||
background: radial-gradient(circle closest-corner, transparent 0, rgba(230, 193, 61, .25) 100%);
|
||||
background: -o-radial-gradient(circle closest-corner, transparent 0, rgba(230, 193, 61, .25) 100%);
|
||||
background: -moz-radial-gradient(circle closest-corner, transparent 0, rgba(230, 193, 61, .25) 100%);
|
||||
background: -webkit-radial-gradient(circle closest-corner, transparent 0, rgba(230, 193, 61, .25) 100%);
|
||||
content: "";
|
||||
mix-blend-mode: lighten;
|
||||
}
|
||||
|
||||
.filter-sierra {
|
||||
-webkit-filter: sepia(.25) contrast(1.5) brightness(.9) hue-rotate(-15deg);
|
||||
filter: sepia(.25) contrast(1.5) brightness(.9) hue-rotate(-15deg);
|
||||
}
|
||||
|
||||
.filter-sierra::before {
|
||||
background: radial-gradient(circle closest-corner, rgba(128, 78, 15, .5) 0, rgba(0, 0, 0, .65) 100%);
|
||||
background: -o-radial-gradient(circle closest-corner, rgba(128, 78, 15, .5) 0, rgba(0, 0, 0, .65) 100%);
|
||||
background: -moz-radial-gradient(circle closest-corner, rgba(128, 78, 15, .5) 0, rgba(0, 0, 0, .65) 100%);
|
||||
background: -webkit-radial-gradient(circle closest-corner, rgba(128, 78, 15, .5) 0, rgba(0, 0, 0, .65) 100%);
|
||||
content: "";
|
||||
mix-blend-mode: screen;
|
||||
}
|
||||
|
||||
.filter-skyline {
|
||||
-webkit-filter: sepia(.15) contrast(1.25) brightness(1.25) saturate(1.2);
|
||||
filter: sepia(.15) contrast(1.25) brightness(1.25) saturate(1.2);
|
||||
}
|
||||
|
||||
.filter-slumber {
|
||||
-webkit-filter: sepia(.35) contrast(1.25) saturate(1.25);
|
||||
filter: sepia(.35) contrast(1.25) saturate(1.25);
|
||||
}
|
||||
|
||||
.filter-slumber::before {
|
||||
background: rgba(125, 105, 24, .2);
|
||||
content: "";
|
||||
mix-blend-mode: darken;
|
||||
}
|
||||
|
||||
.filter-stinson {
|
||||
-webkit-filter: sepia(.35) contrast(1.25) brightness(1.1) saturate(1.25);
|
||||
filter: sepia(.35) contrast(1.25) brightness(1.1) saturate(1.25);
|
||||
}
|
||||
|
||||
.filter-stinson::before {
|
||||
background: rgba(125, 105, 24, .45);
|
||||
content: "";
|
||||
mix-blend-mode: lighten;
|
||||
}
|
||||
|
||||
.filter-sutro {
|
||||
-webkit-filter: sepia(.4) contrast(1.2) brightness(.9) saturate(1.4) hue-rotate(-10deg);
|
||||
filter: sepia(.4) contrast(1.2) brightness(.9) saturate(1.4) hue-rotate(-10deg);
|
||||
}
|
||||
|
||||
.filter-sutro::before {
|
||||
background: radial-gradient(circle closest-corner, transparent 50%, rgba(0, 0, 0, .5) 90%);
|
||||
background: -o-radial-gradient(circle closest-corner, transparent 50%, rgba(0, 0, 0, .5) 90%);
|
||||
background: -moz-radial-gradient(circle closest-corner, transparent 50%, rgba(0, 0, 0, .5) 90%);
|
||||
background: -webkit-radial-gradient(circle closest-corner, transparent 50%, rgba(0, 0, 0, .5) 90%);
|
||||
content: "";
|
||||
mix-blend-mode: darken;
|
||||
}
|
||||
|
||||
.filter-toaster {
|
||||
-webkit-filter: sepia(.25) contrast(1.5) brightness(.95) hue-rotate(-15deg);
|
||||
filter: sepia(.25) contrast(1.5) brightness(.95) hue-rotate(-15deg);
|
||||
}
|
||||
|
||||
.filter-toaster::before {
|
||||
background: radial-gradient(circle, #804e0f, rgba(0, 0, 0, .25));
|
||||
background: -o-radial-gradient(circle, #804e0f, rgba(0, 0, 0, .25));
|
||||
background: -moz-radial-gradient(circle, #804e0f, rgba(0, 0, 0, .25));
|
||||
background: -webkit-radial-gradient(circle, #804e0f, rgba(0, 0, 0, .25));
|
||||
content: "";
|
||||
mix-blend-mode: screen;
|
||||
}
|
||||
|
||||
.filter-valencia {
|
||||
-webkit-filter: sepia(.25) contrast(1.1) brightness(1.1);
|
||||
filter: sepia(.25) contrast(1.1) brightness(1.1);
|
||||
}
|
||||
|
||||
.filter-valencia::before {
|
||||
background: rgba(230, 193, 61, .1);
|
||||
content: "";
|
||||
mix-blend-mode: lighten;
|
||||
}
|
||||
|
||||
.filter-vesper {
|
||||
-webkit-filter: sepia(.35) contrast(1.15) brightness(1.2) saturate(1.3);
|
||||
filter: sepia(.35) contrast(1.15) brightness(1.2) saturate(1.3);
|
||||
}
|
||||
|
||||
.filter-vesper::before {
|
||||
background: rgba(125, 105, 24, .25);
|
||||
content: "";
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
.filter-walden {
|
||||
-webkit-filter: sepia(.35) contrast(.8) brightness(1.25) saturate(1.4);
|
||||
filter: sepia(.35) contrast(.8) brightness(1.25) saturate(1.4);
|
||||
}
|
||||
|
||||
.filter-walden::before {
|
||||
background: rgba(229, 240, 128, .5);
|
||||
content: "";
|
||||
mix-blend-mode: darken;
|
||||
}
|
||||
|
||||
.filter-willow {
|
||||
-webkit-filter: brightness(1.2) contrast(.85) saturate(.05) sepia(.2);
|
||||
filter: brightness(1.2) contrast(.85) saturate(.05) sepia(.2);
|
||||
}
|
||||
|
||||
.filter-xpro-ii {
|
||||
-webkit-filter: sepia(.45) contrast(1.25) brightness(1.75) saturate(1.3) hue-rotate(-5deg);
|
||||
filter: sepia(.45) contrast(1.25) brightness(1.75) saturate(1.3) hue-rotate(-5deg);
|
||||
}
|
||||
|
||||
.filter-xpro-ii::before {
|
||||
background: radial-gradient(circle closest-corner, rgba(0, 91, 154, .35) 0, rgba(0, 0, 0, .65) 100%);
|
||||
background: -o-radial-gradient(circle closest-corner, rgba(0, 91, 154, .35) 0, rgba(0, 0, 0, .65) 100%);
|
||||
background: -moz-radial-gradient(circle closest-corner, rgba(0, 91, 154, .35) 0, rgba(0, 0, 0, .65) 100%);
|
||||
background: -webkit-radial-gradient(circle closest-corner, rgba(0, 91, 154, .35) 0, rgba(0, 0, 0, .65) 100%);
|
||||
content: "";
|
||||
mix-blend-mode: multiply;
|
||||
}
|
152
resources/assets/sass/components/switch.scss
vendored
Normal file
152
resources/assets/sass/components/switch.scss
vendored
Normal file
|
@ -0,0 +1,152 @@
|
|||
$switch-height: calc(#{$input-height} * .8) !default;
|
||||
$switch-height-sm: calc(#{$input-height-sm} * .8) !default;
|
||||
$switch-height-lg: calc(#{$input-height-lg} * .8) !default;
|
||||
$switch-border-radius: $switch-height !default;
|
||||
$switch-bg: $custom-control-indicator-bg !default;
|
||||
$switch-checked-bg: map-get($theme-colors, 'danger') !default;
|
||||
$switch-disabled-bg: $custom-control-indicator-disabled-bg !default;
|
||||
$switch-disabled-color: $custom-control-description-disabled-color !default;
|
||||
$switch-thumb-bg: $white !default;
|
||||
$switch-thumb-border-radius: 50% !default;
|
||||
$switch-thumb-padding: 2px !default;
|
||||
$switch-focus-box-shadow: 0 0 0 $input-btn-focus-width rgba(map-get($theme-colors, 'primary'), .25);
|
||||
$switch-transition: .2s all !default;
|
||||
|
||||
.switch {
|
||||
font-size: $font-size-base;
|
||||
position: relative;
|
||||
|
||||
input {
|
||||
position: absolute;
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
background: none;
|
||||
border: 0;
|
||||
clip: rect(0 0 0 0);
|
||||
clip-path: inset(50%);
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
|
||||
+ label {
|
||||
position: relative;
|
||||
min-width: calc(#{$switch-height} * 2);
|
||||
border-radius: $switch-border-radius;
|
||||
height: $switch-height;
|
||||
line-height: $switch-height;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
user-select: none;
|
||||
vertical-align: middle;
|
||||
text-indent: calc(calc(#{$switch-height} * 2) + .5rem);
|
||||
}
|
||||
|
||||
+ label::before,
|
||||
+ label::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: calc(#{$switch-height} * 2);
|
||||
bottom: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
+ label::before {
|
||||
right: 0;
|
||||
background-color: $switch-bg;
|
||||
border-radius: $switch-border-radius;
|
||||
transition: $switch-transition;
|
||||
}
|
||||
|
||||
+ label::after {
|
||||
top: $switch-thumb-padding;
|
||||
left: $switch-thumb-padding;
|
||||
width: calc(#{$switch-height} - calc(#{$switch-thumb-padding} * 2));
|
||||
height: calc(#{$switch-height} - calc(#{$switch-thumb-padding} * 2));
|
||||
border-radius: $switch-thumb-border-radius;
|
||||
background-color: $switch-thumb-bg;
|
||||
transition: $switch-transition;
|
||||
}
|
||||
|
||||
&:checked + label::before {
|
||||
background-color: $switch-checked-bg;
|
||||
}
|
||||
|
||||
&:checked + label::after {
|
||||
margin-left: $switch-height;
|
||||
}
|
||||
|
||||
&:focus + label::before {
|
||||
outline: none;
|
||||
box-shadow: $switch-focus-box-shadow;
|
||||
}
|
||||
|
||||
&:disabled + label {
|
||||
color: $switch-disabled-color;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
&:disabled + label::before {
|
||||
background-color: $switch-disabled-bg;
|
||||
}
|
||||
}
|
||||
|
||||
// Small variation
|
||||
&.switch-sm {
|
||||
font-size: $font-size-sm;
|
||||
|
||||
input {
|
||||
+ label {
|
||||
min-width: calc(#{$switch-height-sm} * 2);
|
||||
height: $switch-height-sm;
|
||||
line-height: $switch-height-sm;
|
||||
text-indent: calc(calc(#{$switch-height-sm} * 2) + .5rem);
|
||||
}
|
||||
|
||||
+ label::before {
|
||||
width: calc(#{$switch-height-sm} * 2);
|
||||
}
|
||||
|
||||
+ label::after {
|
||||
width: calc(#{$switch-height-sm} - calc(#{$switch-thumb-padding} * 2));
|
||||
height: calc(#{$switch-height-sm} - calc(#{$switch-thumb-padding} * 2));
|
||||
}
|
||||
|
||||
&:checked + label::after {
|
||||
margin-left: $switch-height-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Large variation
|
||||
&.switch-lg {
|
||||
font-size: $font-size-lg;
|
||||
|
||||
input {
|
||||
+ label {
|
||||
min-width: calc(#{$switch-height-lg} * 2);
|
||||
height: $switch-height-lg;
|
||||
line-height: $switch-height-lg;
|
||||
text-indent: calc(calc(#{$switch-height-lg} * 2) + .5rem);
|
||||
}
|
||||
|
||||
+ label::before {
|
||||
width: calc(#{$switch-height-lg} * 2);
|
||||
}
|
||||
|
||||
+ label::after {
|
||||
width: calc(#{$switch-height-lg} - calc(#{$switch-thumb-padding} * 2));
|
||||
height: calc(#{$switch-height-lg} - calc(#{$switch-thumb-padding} * 2));
|
||||
}
|
||||
|
||||
&:checked + label::after {
|
||||
margin-left: $switch-height-lg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ .switch {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
}
|
17
resources/assets/sass/custom.scss
vendored
17
resources/assets/sass/custom.scss
vendored
|
@ -239,7 +239,24 @@ body, button, input, textarea {
|
|||
background-position: 50%;
|
||||
}
|
||||
|
||||
|
||||
.status-photo img {
|
||||
object-fit: contain;
|
||||
max-height: calc(100vh - (6rem));
|
||||
}
|
||||
|
||||
@keyframes fadeInDown {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-1.25em);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
.details-animated[open] {
|
||||
animation-name: fadeInDown;
|
||||
animation-duration: 0.5s;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<span class="text-muted notification-timestamp pl-1">{{$notification->created_at->diffForHumans(null, true, true, true)}}</span>
|
||||
</span>
|
||||
<span class="float-right notification-action">
|
||||
@if($notification->item_id)
|
||||
@if($notification->item_id && $notification->item_type == 'App\Status')
|
||||
<a href="{{$notification->status->url()}}"><img src="{{$notification->status->thumb()}}" width="32px" height="32px"></a>
|
||||
@endif
|
||||
</span>
|
||||
|
@ -70,10 +70,16 @@
|
|||
<span class="text-muted notification-timestamp pl-1">{{$notification->created_at->diffForHumans(null, true, true, true)}}</span>
|
||||
</span>
|
||||
<span class="float-right notification-action">
|
||||
@if($notification->item_id)
|
||||
@if($notification->item_id && $notification->item_type === 'App\Status')
|
||||
@if(is_null($notification->status->in_reply_to_id))
|
||||
<a href="{{$notification->status->url()}}">
|
||||
<div class="notification-image" style="background-image: url('{{$notification->status->thumb()}}')"></div>
|
||||
</a>
|
||||
@else
|
||||
<a href="{{$notification->status->parent()->url()}}">
|
||||
<div class="notification-image" style="background-image: url('{{$notification->status->parent()->thumb()}}')"></div>
|
||||
</a>
|
||||
@endif
|
||||
@endif
|
||||
</span>
|
||||
@break
|
||||
|
@ -81,12 +87,20 @@
|
|||
@endswitch
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
|
||||
<div class="d-flex justify-content-center my-4">
|
||||
{{$notifications->links()}}
|
||||
</div>
|
||||
@else
|
||||
<div class="mt-4">
|
||||
<div class="alert alert-info font-weight-bold">No unread notifications found.</div>
|
||||
</div>
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript" src="{{mix('js/activity.js')}}"></script>
|
||||
@endpush
|
||||
|
|
24
resources/views/account/verify_email.blade.php
Normal file
24
resources/views/account/verify_email.blade.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container mt-4">
|
||||
<div class="col-12 col-md-8 offset-md-2">
|
||||
@if (session('status'))
|
||||
<div class="alert alert-success">
|
||||
{{ session('status') }}
|
||||
</div>
|
||||
@endif
|
||||
<div class="card">
|
||||
<div class="card-header font-weight-bold bg-white">Confirm Email Address</div>
|
||||
<div class="card-body">
|
||||
<p class="lead">You need to confirm your email address (<span class="font-weight-bold">{{Auth::user()->email}}</span>) before you can proceed.</p>
|
||||
<hr>
|
||||
<form method="post">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-primary btn-block py-1 font-weight-bold">Send Confirmation Email</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
12
resources/views/emails/confirm_email.blade.php
Normal file
12
resources/views/emails/confirm_email.blade.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
@component('mail::message')
|
||||
# Email Confirmation
|
||||
|
||||
Please confirm your email address.
|
||||
|
||||
@component('mail::button', ['url' => $verify->url()])
|
||||
Confirm Email
|
||||
@endcomponent
|
||||
|
||||
Thanks,<br>
|
||||
{{ config('app.name') }}
|
||||
@endcomponent
|
|
@ -20,11 +20,9 @@
|
|||
|
||||
<meta name="medium" content="image">
|
||||
<meta name="theme-color" content="#10c5f8">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
|
||||
<link rel="canonical" href="{{request()->url()}}">
|
||||
<link rel="dns-prefetch" href="https://fonts.gstatic.com">
|
||||
<link rel="dns-prefetch" href="https://cdnjs.cloudflare.com">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/simple-line-icons/2.4.1/css/simple-line-icons.min.css" integrity="sha256-7O1DfUu4pybYI7uAATw34eDrgQaWGOfMV/8erfDQz/Q=" crossorigin="anonymous" />
|
||||
<link href="{{ mix('css/app.css') }}" rel="stylesheet">
|
||||
@stack('styles')
|
||||
</head>
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
<footer>
|
||||
<div class="container py-3">
|
||||
<div class="container py-5">
|
||||
<p class="mb-0 text-uppercase font-weight-bold small">
|
||||
<a href="{{route('site.about')}}" class="text-primary pr-2">About Us</a>
|
||||
<a href="{{route('site.help')}}" class="text-primary pr-2">Support</a>
|
||||
<a href="{{route('site.opensource')}}" class="text-primary pr-2">Open Source</a>
|
||||
<a href="{{route('site.language')}}" class="text-primary pr-2">Language</a>
|
||||
<span> | </span>
|
||||
<span class="px-2"></span>
|
||||
<a href="{{route('site.terms')}}" class="text-primary pr-2 pl-2">Terms</a>
|
||||
<a href="{{route('site.privacy')}}" class="text-primary pr-2">Privacy</a>
|
||||
<a href="{{route('site.platform')}}" class="text-primary pr-2">API</a>
|
||||
<span> | </span>
|
||||
<span class="px-2"></span>
|
||||
<a href="#" class="text-primary pr-2 pl-2">Directory</a>
|
||||
<a href="#" class="text-primary pr-2">Profiles</a>
|
||||
<a href="#" class="text-primary">Hashtags</a>
|
||||
<a href="http://pixelfed.org" class="text-dark float-right" rel="noopener">Powered by PixelFed</a>
|
||||
<a href="http://pixelfed.org" class="text-muted float-right" rel="noopener">Powered by PixelFed</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
</a>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
@auth
|
||||
<ul class="navbar-nav ml-auto d-none d-md-block">
|
||||
<form class="form-inline search-form">
|
||||
<input class="form-control mr-sm-2 search-form-input" type="search" placeholder="Search" aria-label="Search">
|
||||
</form>
|
||||
</ul>
|
||||
@endauth
|
||||
|
||||
<ul class="navbar-nav ml-auto">
|
||||
@guest
|
||||
|
@ -29,10 +31,10 @@
|
|||
</a>
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
|
||||
<a class="dropdown-item font-weight-ultralight" href="{{Auth::user()->url()}}">
|
||||
<span class="far fa-user pr-1"></span>
|
||||
<a class="dropdown-item font-weight-ultralight text-truncate" href="{{Auth::user()->url()}}">
|
||||
<img class="img-thumbnail rounded-circle pr-1" src="{{Auth::user()->profile->avatarUrl()}}" width="32px">
|
||||
@{{Auth::user()->username}}
|
||||
<p class="small mb-0">{{__('navmenu.viewMyProfile')}}</p>
|
||||
<p class="small mb-0 text-muted">{{__('navmenu.viewMyProfile')}}</p>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item font-weight-bold" href="{{route('timeline.personal')}}">
|
||||
|
@ -48,12 +50,10 @@
|
|||
<span class="fas fa-user-plus pr-1"></span>
|
||||
{{__('navmenu.remoteFollow')}}
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item font-weight-bold" href="{{route('settings')}}">
|
||||
<span class="fas fa-cog pr-1"></span>
|
||||
{{__('navmenu.settings')}}
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
@if(Auth::user()->is_admin == true)
|
||||
<a class="dropdown-item font-weight-bold" href="{{ route('admin.home') }}">
|
||||
<span class="fas fa-cogs pr-1"></span>
|
||||
|
@ -78,8 +78,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@auth
|
||||
<nav class="breadcrumb d-md-none d-flex">
|
||||
<form class="form-inline search-form mx-auto">
|
||||
<input class="form-control mr-sm-2 search-form-input" type="search" placeholder="Search" aria-label="Search">
|
||||
</form>
|
||||
</nav>
|
||||
@endauth
|
|
@ -8,11 +8,16 @@
|
|||
</div>
|
||||
<div class="col-12 col-md-8 d-flex align-items-center">
|
||||
<div class="profile-details">
|
||||
<div class="username-bar pb-2 d-flex align-items-center">
|
||||
<div class="username-bar pb-2 d-flex align-items-center">
|
||||
<span class="font-weight-ultralight h1">{{$user->username}}</span>
|
||||
@if($is_admin == true)
|
||||
<span class="pl-4">
|
||||
<span class="btn btn-outline-danger font-weight-bold py-0">ADMIN</span>
|
||||
</span>
|
||||
@endif
|
||||
@if($owner == true)
|
||||
<span class="h5 pl-2 b-0">
|
||||
<a class="icon-settings text-muted" href="{{route('settings')}}"></a>
|
||||
<span class="pl-4">
|
||||
<a class="fas fa-cog fa-lg text-muted" href="{{route('settings')}}"></a>
|
||||
</span>
|
||||
@elseif ($is_following == true)
|
||||
<span class="pl-4">
|
||||
|
|
|
@ -27,15 +27,15 @@
|
|||
@foreach($timeline as $status)
|
||||
<div class="col-12 col-md-4 mb-4">
|
||||
<a class="card info-overlay" href="{{$status->url()}}">
|
||||
<div class="square">
|
||||
<div class="square {{$status->firstMedia()->filter_class}}">
|
||||
<div class="square-content" style="background-image: url('{{$status->thumb()}}')"></div>
|
||||
<div class="info-overlay-text">
|
||||
<h5 class="text-white m-auto font-weight-bold">
|
||||
<span class="pr-4">
|
||||
<span class="icon-heart pr-1"></span> {{$status->likes_count}}
|
||||
<span class="far fa-heart fa-lg pr-1"></span> {{$status->likes_count}}
|
||||
</span>
|
||||
<span>
|
||||
<span class="icon-speech pr-1"></span> {{$status->comments_count}}
|
||||
<span class="far fa-comment fa-lg pr-1"></span> {{$status->comments_count}}
|
||||
</span>
|
||||
</h5>
|
||||
</div>
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
<p class="lead">Fediverse is a portmanteau of "federation" and "universe". It is a common, informal name for a somewhat broad federation of social network servers.</p>
|
||||
<p class="lead font-weight-bold text-muted mt-4">Supported Fediverse Projects</p>
|
||||
<ul class="lead pl-4">
|
||||
<li>Mastodon - A federated twitter alternative.</li>
|
||||
<li>Pleroma - A federated twitter alternative.</li>
|
||||
<li><a href="https://joinmastodon.org" rel="nofollow noopener">Mastodon</a> - A federated twitter alternative.</li>
|
||||
<li><a href="https://pleroma.social" rel="nofollow noopener">Pleroma</a> - A federated twitter alternative.</li>
|
||||
</ul>
|
||||
</section>
|
||||
@endsection
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<div class="container px-0 mt-md-4">
|
||||
<div class="card card-md-rounded-0 status-container orientation-{{$status->firstMedia()->orientation ?? 'unknown'}}">
|
||||
<div class="row mx-0">
|
||||
<div class="d-flex d-md-none align-items-center justify-content-between card-header w-100">
|
||||
<div class="d-flex d-md-none align-items-center justify-content-between card-header bg-white w-100">
|
||||
<div class="d-flex align-items-center status-username">
|
||||
<div class="status-avatar mr-2">
|
||||
<img class="img-thumbnail" src="{{$user->avatarUrl()}}" width="24px" height="24px" style="border-radius:12px;">
|
||||
|
@ -14,15 +14,52 @@
|
|||
<a href="{{$user->url()}}" class="username-link font-weight-bold text-dark">{{$user->username}}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="timestamp mb-0">
|
||||
<p class="small text-uppercase mb-0"><a href="{{$status->url()}}" class="text-muted">{{$status->created_at->diffForHumans(null, true, true, true)}}</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-8 status-photo px-0">
|
||||
<img src="{{$status->mediaUrl()}}" width="100%">
|
||||
@if($status->is_nsfw && $status->media_count == 1)
|
||||
<details class="details-animated">
|
||||
<p>
|
||||
<summary>NSFW / Hidden Image</summary>
|
||||
<a class="max-hide-overflow {{$status->firstMedia()->filter_class}}" href="{{$status->url()}}">
|
||||
<img class="card-img-top" src="{{$status->mediaUrl()}}">
|
||||
</a>
|
||||
</p>
|
||||
</details>
|
||||
@elseif(!$status->is_nsfw && $status->media_count == 1)
|
||||
<div class="{{$status->firstMedia()->filter_class}}">
|
||||
<img src="{{$status->mediaUrl()}}" width="100%">
|
||||
</div>
|
||||
@elseif($status->is_nsfw && $status->media_count > 1)
|
||||
|
||||
@elseif(!$status->is_nsfw && $status->media_count > 1)
|
||||
<div id="photoCarousel" class="carousel slide carousel-fade" data-ride="carousel">
|
||||
<ol class="carousel-indicators">
|
||||
@for($i = 0; $i < $status->media_count; $i++)
|
||||
<li data-target="#photoCarousel" data-slide-to="{{$i}}" class="{{$i == 0 ? 'active' : ''}}"></li>
|
||||
@endfor
|
||||
</ol>
|
||||
<div class="carousel-inner">
|
||||
@foreach($status->media()->orderBy('order')->get() as $media)
|
||||
<div class="carousel-item {{$loop->iteration == 1 ? 'active' : ''}}">
|
||||
<figure class="{{$media->filter_class}}">
|
||||
<img class="d-block w-100" src="{{$media->url()}}" alt="{{$status->caption}}">
|
||||
</figure>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<a class="carousel-control-prev" href="#photoCarousel" role="button" data-slide="prev">
|
||||
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
||||
<span class="sr-only">Previous</span>
|
||||
</a>
|
||||
<a class="carousel-control-next" href="#photoCarousel" role="button" data-slide="next">
|
||||
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
||||
<span class="sr-only">Next</span>
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-12 col-md-4 px-0 d-flex flex-column border-left border-md-left-0">
|
||||
<div class="d-md-flex d-none align-items-center justify-content-between card-header">
|
||||
<div class="d-md-flex d-none align-items-center justify-content-between card-header py-3 bg-white">
|
||||
<div class="d-flex align-items-center status-username">
|
||||
<div class="status-avatar mr-2">
|
||||
<img class="img-thumbnail" src="{{$user->avatarUrl()}}" width="24px" height="24px" style="border-radius:12px;">
|
||||
|
@ -31,9 +68,6 @@
|
|||
<a href="{{$user->url()}}" class="username-link font-weight-bold text-dark">{{$user->username}}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="timestamp mb-0">
|
||||
<p class="small text-uppercase mb-0"><a href="{{$status->url()}}" class="text-muted">{{$status->created_at->diffForHumans(null, true, true, true)}}</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-md-column flex-column-reverse h-100">
|
||||
<div class="card-body status-comments">
|
||||
|
@ -46,13 +80,13 @@
|
|||
@foreach($status->comments->reverse()->take(10) as $item)
|
||||
<p class="mb-0">
|
||||
<span class="font-weight-bold pr-1"><bdi><a class="text-dark" href="{{$item->profile->url()}}">{{$item->profile->username}}</a></bdi></span>
|
||||
<span class="comment-text">{!!$item->rendered!!} <a href="{{$item->url()}}" class="text-dark small font-weight-bold float-right">{{$item->created_at->diffForHumans(null, true, true ,true)}}</a></span>
|
||||
<span class="comment-text">{!! $item->rendered ?? e($item->caption) !!} <a href="{{$item->url()}}" class="text-dark small font-weight-bold float-right">{{$item->created_at->diffForHumans(null, true, true ,true)}}</a></span>
|
||||
</p>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body flex-grow-0">
|
||||
<div class="card-body flex-grow-0 py-1">
|
||||
<div class="reactions h3 mb-0">
|
||||
<form class="d-inline-flex like-form pr-3" method="post" action="/i/like" style="display: inline;" data-id="{{$status->id}}" data-action="like">
|
||||
@csrf
|
||||
|
@ -87,9 +121,14 @@
|
|||
<div class="likes font-weight-bold mb-0">
|
||||
<span class="like-count" data-count="{{$status->likes_count}}">{{$status->likes_count}}</span> likes
|
||||
</div>
|
||||
<div class="timestamp">
|
||||
<a href="{{$status->url()}}" class="small text-muted">
|
||||
{{$status->created_at->format('F j, Y')}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-light sticky-md-bottom">
|
||||
<div class="card-footer bg-white sticky-md-bottom">
|
||||
<form class="comment-form" method="post" action="/i/comment" data-id="{{$status->id}}" data-truncate="false">
|
||||
@csrf
|
||||
<input type="hidden" name="item" value="{{$status->id}}">
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<div class="text-right" style="flex-grow:1;">
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-link text-dark no-caret dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="Post options">
|
||||
<span class="icon-options"></span>
|
||||
<span class="fas fa-ellipsis-v fa-lg text-muted"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenuButton">
|
||||
<a class="dropdown-item" href="{{$item->url()}}">Go to post</a>
|
||||
|
@ -15,6 +15,7 @@
|
|||
<a class="dropdown-item" href="#">Embed</a>
|
||||
@if(Auth::check())
|
||||
@if(Auth::user()->profile->id === $item->profile->id || Auth::user()->is_admin == true)
|
||||
<a class="dropdown-item" href="{{$item->editUrl()}}">Edit</a>
|
||||
<form method="post" action="/i/delete">
|
||||
@csrf
|
||||
<input type="hidden" name="type" value="post">
|
||||
|
@ -28,9 +29,20 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a class="max-hide-overflow" href="{{$item->url()}}">
|
||||
@if($item->is_nsfw)
|
||||
<details class="details-animated">
|
||||
<p>
|
||||
<summary>NSFW / Hidden Image</summary>
|
||||
<a class="max-hide-overflow {{$item->firstMedia()->filter_class}}" href="{{$item->url()}}">
|
||||
<img class="card-img-top" src="{{$item->mediaUrl()}}">
|
||||
</a>
|
||||
</p>
|
||||
</details>
|
||||
@else
|
||||
<a class="max-hide-overflow {{$item->firstMedia()->filter_class}}" href="{{$item->url()}}">
|
||||
<img class="card-img-top" src="{{$item->mediaUrl()}}">
|
||||
</a>
|
||||
@endif
|
||||
<div class="card-body">
|
||||
<div class="reactions h3">
|
||||
<form class="like-form pr-3" method="post" action="/i/like" style="display: inline;" data-id="{{$item->id}}" data-action="like" data-count="{{$item->likes_count}}">
|
||||
|
@ -62,7 +74,7 @@
|
|||
</div>
|
||||
@if($item->comments()->count() > 3)
|
||||
<div class="more-comments">
|
||||
<a class="text-muted" href="#">Load more comments</a>
|
||||
<a class="text-muted" href="{{$item->url()}}">Load more comments</a>
|
||||
</div>
|
||||
@endif
|
||||
<div class="comments">
|
||||
|
@ -73,7 +85,7 @@
|
|||
<a class="text-dark" href="{{$status->profile->url()}}">{{$status->profile->username}}</a>
|
||||
</bdi>
|
||||
</span>
|
||||
<span class="comment-text">{!!$status->rendered!!}</span>
|
||||
<span class="comment-text">{!! $item->rendered ?? e($item->caption) !!}</span>
|
||||
<span class="float-right">
|
||||
<a href="{{$status->url()}}" class="text-dark small font-weight-bold">
|
||||
{{$status->created_at->diffForHumans(null, true, true, true)}}
|
||||
|
@ -81,12 +93,6 @@
|
|||
</span>
|
||||
</p>
|
||||
@else
|
||||
@foreach($item->comments->reverse()->take(3) as $comment)
|
||||
<p class="mb-0">
|
||||
<span class="font-weight-bold pr-1"><bdi><a class="text-dark" href="{{$comment->profile->url()}}">{{$comment->profile->username}}</a></bdi></span>
|
||||
<span class="comment-text">{{ str_limit($comment->caption, 125) }}</span>
|
||||
</p>
|
||||
@endforeach
|
||||
@endif
|
||||
</div>
|
||||
<div class="timestamp pt-1">
|
||||
|
|
|
@ -1,23 +1,75 @@
|
|||
<div class="card">
|
||||
<div class="card-header font-weight-bold">New Post</div>
|
||||
<div class="card-body" id="statusForm">
|
||||
@if (session('error'))
|
||||
<div class="alert alert-danger">
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
<form method="post" action="/timeline" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<input type="hidden" name="filter_name" value="">
|
||||
<input type="hidden" name="filter_class" value="">
|
||||
<div class="form-group">
|
||||
<label class="font-weight-bold text-muted small">Upload Image</label>
|
||||
<input type="file" class="form-control-file" name="photo" accept="image/*">
|
||||
<input type="file" class="form-control-file" id="fileInput" name="photo[]" accept="image/*" multiple="">
|
||||
<small class="form-text text-muted">
|
||||
Max Size: @maxFileSize(). Supported formats: jpeg, png, gif, bmp.
|
||||
Max Size: @maxFileSize(). Supported formats: jpeg, png, gif, bmp. Limited to {{config('pixelfed.max_album_length')}} photos per post.
|
||||
</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="font-weight-bold text-muted small">Caption</label>
|
||||
<input type="text" class="form-control" name="caption" placeholder="Add a caption here">
|
||||
<input type="text" class="form-control" name="caption" placeholder="Add a caption here" autocomplete="off">
|
||||
<small class="form-text text-muted">
|
||||
Max length: {{config('pixelfed.max_caption_length')}} characters.
|
||||
</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-primary btn-sm px-3 py-1 font-weight-bold" type="button" data-toggle="collapse" data-target="#collapsePreview" aria-expanded="false" aria-controls="collapsePreview">
|
||||
Options
|
||||
</button>
|
||||
<div class="collapse" id="collapsePreview">
|
||||
|
||||
<div class="form-group pt-3">
|
||||
<label class="font-weight-bold text-muted small">CW/NSFW</label>
|
||||
<div class="switch switch-sm">
|
||||
<input type="checkbox" class="switch" id="cw-switch" name="cw">
|
||||
<label for="cw-switch" class="small font-weight-bold">(Default off)</label>
|
||||
</div>
|
||||
<small class="form-text text-muted">
|
||||
Please mark all NSFW and controversial content, as per our content policy.
|
||||
</small>
|
||||
</div>
|
||||
|
||||
{{-- <div class="form-group">
|
||||
<label class="font-weight-bold text-muted small">Visibility</label>
|
||||
<div class="switch switch-sm">
|
||||
<input type="checkbox" class="switch" id="visibility-switch" name="visibility">
|
||||
<label for="visibility-switch" class="small font-weight-bold">Public | Followers-only</label>
|
||||
</div>
|
||||
<small class="form-text text-muted">
|
||||
Toggle this to limit this post to your followers only.
|
||||
</small>
|
||||
</div> --}}
|
||||
|
||||
<div class="form-group d-none form-preview">
|
||||
<label class="font-weight-bold text-muted small">Photo Preview</label>
|
||||
<figure class="filterContainer">
|
||||
<img class="filterPreview img-fluid">
|
||||
</figure>
|
||||
<small class="form-text text-muted font-weight-bold">
|
||||
No filter selected.
|
||||
</small>
|
||||
</div>
|
||||
<div class="form-group d-none form-filters">
|
||||
<label for="filterSelectDropdown" class="font-weight-bold text-muted small">Select Filter</label>
|
||||
<select class="form-control" id="filterSelectDropdown">
|
||||
<option value="none" selected="">No Filter</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-outline-primary btn-block">Post</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -25,7 +25,7 @@ Route::domain(config('pixelfed.domain.admin'))->group(function() {
|
|||
Route::get('media/list', 'AdminController@media')->name('admin.media');
|
||||
});
|
||||
|
||||
Route::domain(config('pixelfed.domain.app'))->group(function() {
|
||||
Route::domain(config('pixelfed.domain.app'))->middleware('validemail')->group(function() {
|
||||
|
||||
Route::view('/', 'welcome');
|
||||
|
||||
|
@ -62,6 +62,9 @@ Route::domain(config('pixelfed.domain.app'))->group(function() {
|
|||
Route::post('follow', 'FollowerController@store');
|
||||
Route::post('bookmark', 'BookmarkController@store');
|
||||
Route::get('lang/{locale}', 'SiteController@changeLocale');
|
||||
Route::get('verify-email', 'AccountController@verifyEmail');
|
||||
Route::post('verify-email', 'AccountController@sendVerifyEmail');
|
||||
Route::get('confirm-email/{userToken}/{randomToken}', 'AccountController@confirmVerifyEmail');
|
||||
|
||||
Route::group(['prefix' => 'report'], function() {
|
||||
Route::get('/', 'ReportController@showForm')->name('report.form');
|
||||
|
|
1
webpack.mix.js
vendored
1
webpack.mix.js
vendored
|
@ -12,6 +12,7 @@ let mix = require('laravel-mix');
|
|||
*/
|
||||
|
||||
mix.js('resources/assets/js/app.js', 'public/js')
|
||||
.js('resources/assets/js/activity.js', 'public/js')
|
||||
.js('resources/assets/js/timeline.js', 'public/js')
|
||||
.sass('resources/assets/sass/app.scss', 'public/css')
|
||||
.version();
|
||||
|
|
Loading…
Reference in a new issue