From 0e316aabdc9a8ab2d6234e037aaecccfa3df54fa Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 9 Jun 2018 14:42:35 -0600 Subject: [PATCH 01/27] Add activity.js, infinite scroll for notifications --- public/js/activity.js | Bin 0 -> 768 bytes public/js/timeline.js | Bin 790 -> 790 bytes public/mix-manifest.json | Bin 184 -> 250 bytes resources/assets/js/activity.js | 10 ++++++++++ 4 files changed, 10 insertions(+) create mode 100644 public/js/activity.js create mode 100644 resources/assets/js/activity.js diff --git a/public/js/activity.js b/public/js/activity.js new file mode 100644 index 0000000000000000000000000000000000000000..be031f9af83935221c80bb31e21aa3f8bdcc4cd9 GIT binary patch literal 768 zcmaJfb9R@g{}Ri#?jr zd-L9m*29DyS&y7V`fcJ0b;|9MTmknY*@5GC|3gHeDdMWe3SNVcG`1BIbxrAH8!uh6 z-pNa`NjbL{5LHlToa1r9$|$cfh;ndxy}jl#sAo+QRHw0gd%dXQBvBS!pnMI*+uOs_ zPv}VXFj$1I(Fce$pRT3O<6sX{G*1pr+HiV?%V{eQK#k8L7k<3qUq(Uq_oViF7{B;_ za`5S0fk=z5+SE*ra`TVkyZs`cqhy8^xe{wTf77lc7ru*=5IuRC1E`}JA6{_rbRJk?)ER+Dv`kwAXBaa5a&m5WfeXa2zs)E?M|Rg!NW>9JJRM5{S=sJ5nfiG z%XZKbJa*BS$3Zd$L&xT}-+qtqN=%v%0Q*w6eGjrL<37hb0Z}kE(IV^($6Z^PfRY!EXypZ)XOSX jvceFu&rGp3H!@C1OR}^`N=iz$G)uHhF}6%o;;IDzn`j+> delta 30 kcmeyxxPx)RLh-Z|bJNrmLm*{loSI}}U~Xn$uEbRf0HfOpKL7v# diff --git a/resources/assets/js/activity.js b/resources/assets/js/activity.js new file mode 100644 index 000000000..b1b72d1b8 --- /dev/null +++ b/resources/assets/js/activity.js @@ -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, + }); +}); From 63343ae5033035d44b25ed4448cd498f8e762fbb Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 9 Jun 2018 16:29:36 -0600 Subject: [PATCH 02/27] Add basic CW/NSFW support --- app/Http/Controllers/StatusController.php | 6 +- public/css/app.css | Bin 200971 -> 202777 bytes public/mix-manifest.json | Bin 250 -> 250 bytes resources/assets/sass/_variables.scss | 14 ++ resources/assets/sass/app.scss | 4 +- resources/assets/sass/components/switch.scss | 152 ++++++++++++++++++ .../views/timeline/partial/new-form.blade.php | 12 +- 7 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 resources/assets/sass/components/switch.scss diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php index 27cf768f8..4e5c2e8d4 100644 --- a/app/Http/Controllers/StatusController.php +++ b/app/Http/Controllers/StatusController.php @@ -33,9 +33,11 @@ class StatusController extends Controller $this->validate($request, [ 'photo' => 'required|mimes:jpeg,png,bmp,gif|max:' . config('pixelfed.max_photo_size'), - 'caption' => 'string|max:' . config('pixelfed.max_caption_length') + 'caption' => 'string|max:' . config('pixelfed.max_caption_length'), + 'cw' => 'nullable|string' ]); + $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}"; @@ -45,6 +47,8 @@ class StatusController extends Controller $status = new Status; $status->profile_id = $profile->id; $status->caption = $request->caption; + $status->is_nsfw = $cw; + $status->save(); $media = new Media; diff --git a/public/css/app.css b/public/css/app.css index 656378808792a6c58533bda671cf2adeefcb083e..4fc774d1919e744b4b6828b87f8a69419855ccb5 100644 GIT binary patch delta 3297 zcma)8TWl0%6waA;w=IyC(r%$ZaZ4?<&|UW0-JLCvifQ7dNEIrHD9rB6wga;}>+F=G zO)W|^Dk{Z3oM<9#X%&lHwiFnmLC_}%MlcfPfkb%m_CjJ*8iK@sF1y`r7bSh@&N=`8 zopZkPoinrd;G7SVbCS&?l%Jhw8KDZue=NzPmg9|fm_5*U*qT0sUYqj^qxkZBm%KdCGBuXqN*}|eAN_35b zWFBY&ccsq}@=f}n$@t%k}ER=geUjutG!xp8(DphO2QvrT#J_=g`<^4SnT})1I9fk$CXb85XP>D1=#c2{6 z>@IITZW|`N|1bp2=75v+Mk1=gt2{jn=O|T^<0H_5RU=S}(NX9&b$9YIhrf@4VmRyY z+mGScT+P1R%C27C>ae;xJves^7UJh4@DQ#&1VwoH6Ie5As^uzdo$6^VN*mES23G7J zA;erc1lv^n>M^LrHKXt@{_-i*7{Lj0Z>peyF$hj6`{o#21AQRQeg^AJ0Z)T7fNkwy z!DUClZalv?1`8DF2-LyU5Mc5sbZaw!O~>GkG$fWTCHnaF7;HAHb4J)nE`!=B9nBav z96Sy!sk7SUd&gm`NgFL3`uV7NhrqsC*eoq+7jG*3f`QZqE&72@Cm|z`!v+1ua#r`G+Z%m zRAESgXx5Dv71F&w6{ys1C?t?KvL}1(jKE2h|j8Y2o`DyJOSzkpD2y_{M#<=5A9uj*fgbC*!HiyRJ* z&*z?&tZu}31+@roo2Y8#dkgiO&rtdKQCNaETB!@up7WI}>#4srW-dKL?bMigbR%`% zOt?B!^c?k(%31LwwN~?Nn54c~&}dI|^K!VeCnCmVTY`U?qwN8*?t^hL!OOfDqa{vY zWPT^tYn-(5v3M7LRhU=a*U9l6oigo=?+SMFtlX*n3Nhgw9g^4;W9gU}>l{|?uRdt&=0ZDo*`~T|afTr9u>>dAc^$R&+W8qqaVIB51hJd$bdpiR%fIcBmLjmj>}>lC0{>LCVzPFnCVaA=Z4Xi9c=rs9eI?-W9 z2-oSvT5VQOd{=#n-y9yj9kXplKS=X&{}HGFeE^*gnin1J2=TazB zhjc28Br*rXnKc7m^=mMgJp{TfE$}{~PPe@=L*cojq!gW+KsC^R=Vi1eOG#SrEGd!2 zV`wSUcR%C@XubwB{l3uAGw|x^@@ZrX9rxkUqc0d^ak%WB=`e2pZ`PVfk(eE# sFPlX@%*Gxs7R-s990x#LdfGFVtvYjCz?%T;^P2 zOo(xY#5exXfgp^rtz>|o(IrA+G%;~;Ka7iU%`_&u_-nt~WkdaXdJZis<5$1Fm*>4c z@A-Ic^T=nL=XOjOJZ<4vZ2sX1X3~i#m7YKoZ5u$*=#ewB-XCu1psqNo<}aO@-=z!1 zVxuQ-*+#FWibwxi$^4d%{*Ve71F=X{fSA*dl^SJFSiI>}3X)N3aY;TOeQ1JHee;VZ zL}7`91|p4;+Z%}Y57s_dD;;{Xi8q?@+dXzg<8}LGujI>97MJ5Tv#D-=xowTkhIcgl zHL;f3;lce%fgRzYc(gy>92puIinrH$6yZ^K__c%0hvF{}687PNYLCYshz1Hw{Zb@C zPjsRe5{=EmMm;-GX7;$eYI&DB@wnseQOMhc)0G0F0N57^$LK~Eme&X7e{`eOu1saQ z3sz++bmV!_%WV2I-UmAw_Mu*6o|$4nfQ&F>Wuv91@o0XO;??wBZeLT@W_KSvYob+A zq7QQ$l_s#;>A-U$x$Av!QFkxO>Az;r5vTu5_R@A$E3NL7jRab}B96W`_geu$;Z4*^1w%1O>Obz3(^P6M% zhN&>gNi@>i6R7!U67LzEQcFzOzds3{)9(_hSIIDi3Qb=(g%NXh;G$!6byCnIIfbB> zigy~Hs{WU!@w4XU>19^xnSzmioyL}ohnWsep<8ov&!A&nHVn_;3iKH=QE(Q$Ca)yB zymElXXYr8shhLw?cHD(BobPVp2NHAMWtmoEEGJCy&8>=H^75SrB7YxhYI5=-2{EXk-x%Z8-)P#4NsF#CJKjd+F>K7|e5%HRA(c z!pes^_8YR+{PIQE+qEsW(ba^=raT3gvc)@6IH{rJb&In!_Fw}l@mFp_)*G{TiI!Fb zXTMrO-zIT4#F+|3U+SlSy5Z)J{EIzCok#YOXrrY%66yC95I-zO#igbn^~|ZBW=iW> zgRadd@j3&$U{uS#v6ET&-$iW3xKU!Cmoo!aBN`NN8n-bEl~~zU>T$4&%xhcDMEM-7 zn$*xw4(1dms#RoNaH29oDzdR^{->2~k~Q8WgX})C1=+W%fD1vTIsi)VW^d?3WBBk> ZY)LI
- + Max length: {{config('pixelfed.max_caption_length')}} characters.
+
+ +
+ + +
+ + Please mark all NSFW and controversial content, as per our content policy. + +
From 545efbeee3b82a64650a821e39088185ee0bca86 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 9 Jun 2018 17:30:54 -0600 Subject: [PATCH 03/27] Update AccountController, add pagination to notifications --- app/Http/Controllers/AccountController.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 4a0b5bd5f..6f5eeea43 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; +use Carbon\Carbon; use Auth, Cache, Redis; use App\{Notification, Profile, User}; @@ -15,10 +16,17 @@ 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')); } From 40d1b5342a42066e6c43815e47e332aaff95cf8f Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 9 Jun 2018 17:31:14 -0600 Subject: [PATCH 04/27] Update ProfileController --- app/Http/Controllers/ProfileController.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index 9c7fa9041..4e25bd236 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -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')); } } From 0cc736d1099dc507c3420bdd210cb4235e7fdd46 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 9 Jun 2018 17:31:48 -0600 Subject: [PATCH 05/27] Update Profile model --- app/Profile.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/Profile.php b/app/Profile.php index 3c4b27cea..b0bcd3da3 100644 --- a/app/Profile.php +++ b/app/Profile.php @@ -14,6 +14,11 @@ class Profile extends Model protected $visible = ['id', 'username', 'name']; + public function user() + { + return $this->belongsTo(User::class); + } + public function url($suffix = '') { return url($this->username . $suffix); From 2726f905843edd7b9bf4c6292e6b8d0d8e3c3e46 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 9 Jun 2018 17:32:07 -0600 Subject: [PATCH 06/27] Update Status model --- app/Status.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/Status.php b/app/Status.php index 68e65410a..dd9bf98c4 100644 --- a/app/Status.php +++ b/app/Status.php @@ -25,6 +25,9 @@ class Status extends Model public function thumb() { + if($this->media->count() == 0) { + return "data:image/gif;base64,R0lGODlhAQABAIAAAMLCwgAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="; + } return url(Storage::url($this->firstMedia()->thumbnail_path)); } From 0b85810a33fabb906496243b0cb2384bdd5c15a5 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 9 Jun 2018 17:32:44 -0600 Subject: [PATCH 07/27] Update master layout, remove line-icons --- resources/views/layouts/app.blade.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 83a10462a..b07d4a3f3 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -20,11 +20,9 @@ + - - - @stack('styles') From b6706b626a9145231b1851e92c630a10e4616bc9 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 9 Jun 2018 17:34:53 -0600 Subject: [PATCH 08/27] Replace line-icons with font awesome icons --- resources/views/profile/partial/user-info.blade.php | 11 ++++++++--- resources/views/profile/show.blade.php | 4 ++-- resources/views/status/template.blade.php | 13 ++++++++++++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/resources/views/profile/partial/user-info.blade.php b/resources/views/profile/partial/user-info.blade.php index 4720c2da3..14575f18a 100644 --- a/resources/views/profile/partial/user-info.blade.php +++ b/resources/views/profile/partial/user-info.blade.php @@ -8,11 +8,16 @@
-
+
{{$user->username}} + @if($is_admin == true) + + ADMIN + + @endif @if($owner == true) - - + + @elseif ($is_following == true) diff --git a/resources/views/profile/show.blade.php b/resources/views/profile/show.blade.php index f731da04e..d9fa85c54 100644 --- a/resources/views/profile/show.blade.php +++ b/resources/views/profile/show.blade.php @@ -32,10 +32,10 @@
- {{$status->likes_count}} + {{$status->likes_count}} - {{$status->comments_count}} + {{$status->comments_count}}
diff --git a/resources/views/status/template.blade.php b/resources/views/status/template.blade.php index 09e3a6004..e43215bf8 100644 --- a/resources/views/status/template.blade.php +++ b/resources/views/status/template.blade.php @@ -7,7 +7,7 @@
+ @if($item->is_nsfw) +
+

+

NSFW / Hidden Image + + + +

+
+ @else + @endif
@endsection + +@push('scripts') + +@endpush diff --git a/webpack.mix.js b/webpack.mix.js index 27959585c..b99329cd3 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -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(); From 40872a41591ee347dd8f7bc32685313e550c3bd6 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 9 Jun 2018 17:36:45 -0600 Subject: [PATCH 12/27] Update status template --- resources/views/status/show.blade.php | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/resources/views/status/show.blade.php b/resources/views/status/show.blade.php index 02448e34f..80036fdfb 100644 --- a/resources/views/status/show.blade.php +++ b/resources/views/status/show.blade.php @@ -5,7 +5,7 @@
-
+
- -
+
@csrf @@ -87,9 +81,14 @@ +
-
+ @if($status->is_nsfw) +
+

+

NSFW / Hidden Image + + + +

+
+ @else + @endif
diff --git a/resources/views/status/template.blade.php b/resources/views/status/template.blade.php index e43215bf8..2e56e6ee5 100644 --- a/resources/views/status/template.blade.php +++ b/resources/views/status/template.blade.php @@ -29,7 +29,7 @@
@if($item->is_nsfw) -
+

NSFW / Hidden Image From 3f0ad3ffe2c3e192091a026644fe60a3ab46fa69 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 13 Jun 2018 17:14:10 -0600 Subject: [PATCH 16/27] Update StatusController, support multiple uploads --- app/Http/Controllers/StatusController.php | 42 ++++++++++++------- app/Jobs/StatusPipeline/NewStatusPipeline.php | 11 ++--- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php index 4e5c2e8d4..1ce080245 100644 --- a/app/Http/Controllers/StatusController.php +++ b/app/Http/Controllers/StatusController.php @@ -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,16 +33,16 @@ class StatusController extends Controller $user = Auth::user(); $this->validate($request, [ - 'photo' => 'required|mimes:jpeg,png,bmp,gif|max:' . config('pixelfed.max_photo_size'), + 'photo.*' => 'required|mimes:jpeg,png,bmp,gif|max:' . config('pixelfed.max_photo_size'), 'caption' => 'string|max:' . config('pixelfed.max_caption_length'), - 'cw' => 'nullable|string' + 'cw' => 'nullable|string', + 'filter_class' => 'nullable|string', + 'filter_name' => 'nullable|string', ]); $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; @@ -51,17 +52,28 @@ class StatusController extends Controller $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()); diff --git a/app/Jobs/StatusPipeline/NewStatusPipeline.php b/app/Jobs/StatusPipeline/NewStatusPipeline.php index 01392aa47..8939dd9ad 100644 --- a/app/Jobs/StatusPipeline/NewStatusPipeline.php +++ b/app/Jobs/StatusPipeline/NewStatusPipeline.php @@ -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(); From 5cb3e5c17b488e2f261741175a3821964339bbfc Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 13 Jun 2018 17:14:44 -0600 Subject: [PATCH 17/27] Add new media migration --- ...6_11_030049_add_filters_to_media_table.php | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 database/migrations/2018_06_11_030049_add_filters_to_media_table.php diff --git a/database/migrations/2018_06_11_030049_add_filters_to_media_table.php b/database/migrations/2018_06_11_030049_add_filters_to_media_table.php new file mode 100644 index 000000000..5a3dbf73d --- /dev/null +++ b/database/migrations/2018_06_11_030049_add_filters_to_media_table.php @@ -0,0 +1,34 @@ +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'); + }); + } +} From 4e51fbd5eba9f3e4150af46ae3bdfb190126b554 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 13 Jun 2018 18:52:42 -0600 Subject: [PATCH 18/27] Add soft-deletes --- app/Avatar.php | 8 +++ app/Jobs/StatusPipeline/StatusDelete.php | 5 +- app/Like.php | 10 ++++ app/Media.php | 12 +++- app/Mention.php | 9 +++ app/Notification.php | 41 ++++++++----- app/Profile.php | 9 +++ app/Status.php | 18 +++++- app/User.php | 10 +++- ...6_14_001318_add_soft_deletes_to_models.php | 58 +++++++++++++++++++ 10 files changed, 159 insertions(+), 21 deletions(-) create mode 100644 database/migrations/2018_06_14_001318_add_soft_deletes_to_models.php diff --git a/app/Avatar.php b/app/Avatar.php index a7f8e4e67..b72510765 100644 --- a/app/Avatar.php +++ b/app/Avatar.php @@ -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']; } diff --git a/app/Jobs/StatusPipeline/StatusDelete.php b/app/Jobs/StatusPipeline/StatusDelete.php index 571b41a55..30aecd7e2 100644 --- a/app/Jobs/StatusPipeline/StatusDelete.php +++ b/app/Jobs/StatusPipeline/StatusDelete.php @@ -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; @@ -60,6 +60,9 @@ class StatusDelete implements ShouldQueue } $status->likes()->delete(); + Notification::whereItemType('App\Status') + ->whereItemId($status->id) + ->delete(); StatusHashtag::whereStatusId($status->id)->delete(); $status->delete(); diff --git a/app/Like.php b/app/Like.php index a4ce9f0a8..c70b647bc 100644 --- a/app/Like.php +++ b/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'); diff --git a/app/Media.php b/app/Media.php index 8cc2ffd1e..7c9138965 100644 --- a/app/Media.php +++ b/app/Media.php @@ -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; diff --git a/app/Mention.php b/app/Mention.php index 3473c2924..bc76bdc97 100644 --- a/app/Mention.php +++ b/app/Mention.php @@ -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() { diff --git a/app/Notification.php b/app/Notification.php index c40e0a553..9aef5b197 100644 --- a/app/Notification.php +++ b/app/Notification.php @@ -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'); + } } diff --git a/app/Profile.php b/app/Profile.php index b0bcd3da3..009ed2cbf 100644 --- a/app/Profile.php +++ b/app/Profile.php @@ -5,9 +5,18 @@ 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', ]; diff --git a/app/Status.php b/app/Status.php index 07879f510..fe3fc26d2 100644 --- a/app/Status.php +++ b/app/Status.php @@ -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); @@ -43,6 +52,11 @@ class Status extends Model return url($path); } + public function editUrl() + { + return $this->url() . '/edit'; + } + public function mediaUrl() { $media = $this->firstMedia(); diff --git a/app/User.php b/app/User.php index 33297e481..38edc3e9d 100644 --- a/app/User.php +++ b/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. diff --git a/database/migrations/2018_06_14_001318_add_soft_deletes_to_models.php b/database/migrations/2018_06_14_001318_add_soft_deletes_to_models.php new file mode 100644 index 000000000..a839ddf74 --- /dev/null +++ b/database/migrations/2018_06_14_001318_add_soft_deletes_to_models.php @@ -0,0 +1,58 @@ +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() + { + // + } +} From 231884c770e0371ad2f02f9f0f91e0573cd2a309 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 13 Jun 2018 18:54:27 -0600 Subject: [PATCH 19/27] Update view entity encoding --- app/Http/Controllers/CommentController.php | 4 +-- app/Http/Controllers/StatusController.php | 2 +- resources/views/status/show.blade.php | 39 +++++++++++++++++++--- resources/views/status/template.blade.php | 9 ++--- 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php index 1ec7bbf4d..8b8eded8e 100644 --- a/app/Http/Controllers/CommentController.php +++ b/app/Http/Controllers/CommentController.php @@ -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(); diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php index 1ce080245..704beea6c 100644 --- a/app/Http/Controllers/StatusController.php +++ b/app/Http/Controllers/StatusController.php @@ -47,7 +47,7 @@ class StatusController extends Controller $status = new Status; $status->profile_id = $profile->id; - $status->caption = $request->caption; + $status->caption = strip_tags($request->caption); $status->is_nsfw = $cw; $status->save(); diff --git a/resources/views/status/show.blade.php b/resources/views/status/show.blade.php index 80e7e41d3..8d2e27d67 100644 --- a/resources/views/status/show.blade.php +++ b/resources/views/status/show.blade.php @@ -16,17 +16,46 @@
- @if($status->is_nsfw) + @if($status->is_nsfw && $status->media_count == 1)

NSFW / Hidden Image -
+

- @else - + @elseif(!$status->is_nsfw && $status->media_count == 1) +
+ +
+ @elseif($status->is_nsfw && $status->media_count > 1) + + @elseif(!$status->is_nsfw && $status->media_count > 1) + @endif
@@ -51,7 +80,7 @@ @foreach($status->comments->reverse()->take(10) as $item)

{{$item->profile->username}} - {!!$item->rendered!!} {{$item->created_at->diffForHumans(null, true, true ,true)}} + {!! $item->rendered ?? e($item->caption) !!} {{$item->created_at->diffForHumans(null, true, true ,true)}}

@endforeach
diff --git a/resources/views/status/template.blade.php b/resources/views/status/template.blade.php index 2e56e6ee5..7a3910887 100644 --- a/resources/views/status/template.blade.php +++ b/resources/views/status/template.blade.php @@ -15,6 +15,7 @@ Embed @if(Auth::check()) @if(Auth::user()->profile->id === $item->profile->id || Auth::user()->is_admin == true) + Edit
@csrf @@ -32,13 +33,13 @@

NSFW / Hidden Image - +

@else - + @endif @@ -84,7 +85,7 @@ {{$status->profile->username}} - {!!$status->rendered!!} + {!! $item->rendered ?? e($item->caption) !!} {{$status->created_at->diffForHumans(null, true, true, true)}} @@ -95,7 +96,7 @@ @foreach($item->comments->reverse()->take(3) as $comment)

{{$comment->profile->username}} - {{ str_limit($comment->caption, 125) }} + {!! str_limit($item->rendered ?? e($item->caption), 150) !!}

@endforeach @endif From 596f335dc6ddfb909b3233568590016eed6e42d1 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 13 Jun 2018 19:47:08 -0600 Subject: [PATCH 20/27] Update StatusEntityLexer --- app/Jobs/StatusPipeline/StatusEntityLexer.php | 78 +++++++++++++++---- 1 file changed, 62 insertions(+), 16 deletions(-) diff --git a/app/Jobs/StatusPipeline/StatusEntityLexer.php b/app/Jobs/StatusPipeline/StatusEntityLexer.php index c1d09ccb7..c9dff4d59 100644 --- a/app/Jobs/StatusPipeline/StatusEntityLexer.php +++ b/app/Jobs/StatusPipeline/StatusEntityLexer.php @@ -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); + } + } + } From 47df007a7e5f8096298e2972fee04e55e3b4552b Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 13 Jun 2018 20:57:16 -0600 Subject: [PATCH 21/27] Add Photo Filters and Photo Albums --- app/Http/Controllers/StatusController.php | 4 + config/pixelfed.php | 10 + public/css/app.css | Bin 203269 -> 214298 bytes public/js/app.js | Bin 306988 -> 309793 bytes public/mix-manifest.json | Bin 250 -> 250 bytes resources/assets/js/bootstrap.js | 1 + resources/assets/js/components/statusform.js | 110 +++++ resources/assets/sass/app.scss | 2 + resources/assets/sass/components/filters.scss | 445 ++++++++++++++++++ resources/assets/sass/custom.scss | 15 + resources/views/profile/show.blade.php | 2 +- .../views/timeline/partial/new-form.blade.php | 66 ++- 12 files changed, 642 insertions(+), 13 deletions(-) create mode 100644 resources/assets/js/components/statusform.js create mode 100644 resources/assets/sass/components/filters.scss diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php index 704beea6c..67f204cdf 100644 --- a/app/Http/Controllers/StatusController.php +++ b/app/Http/Controllers/StatusController.php @@ -40,6 +40,10 @@ class StatusController extends Controller '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); diff --git a/config/pixelfed.php b/config/pixelfed.php index 9a872e74c..a3ec46783 100644 --- a/config/pixelfed.php +++ b/config/pixelfed.php @@ -96,5 +96,15 @@ 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), ]; \ No newline at end of file diff --git a/public/css/app.css b/public/css/app.css index dee2a793158e645d59bf5df6ca61e432b492f17a..d3c5687bcf3ef461d54d06ad8a6c1303106209c3 100644 GIT binary patch delta 11092 zcmbta&5qkP5Jr<*(w|!oJ-G?CT?djPdDm;N7kz*L?X9<>2U(_V)w1ML@@||om>$wg zZ$%FQ`WylJRDFjIDTyK}QY(9rOV$vF^YhI&Khhr`KmF&=&whXZ$@@niAOH6`JbCi+ z#n*#ZX1m9Fa69_}3~f*88~^W!sm#I4bs(?80>P zGFHyMc==P5gn9nryJegdg#P??m*sI0XX%WRBrM`v@=ki<8}`U-PL>%ZZx?aCOTxo! zo@CMHW=-PNx|jvNe|Gb?_w*~sb~FFxE?yMt^2axBoG!@gS@6y)?{b6d$>gnjN9LQj zaLeCjIoZYGxi=mT)_da8tOyHo?q2u{vKkKZ5Y1pe1m5NFruzgKj)J`-s)1i7{A2ZNVddNVES;Fu{ zQXzLv!!!+T2)tB6HbPxhKuR(5uGKslu{0?Y18AK~50xjWon@QkVAGpv+Qb07mgejS zDXYhgvO-r?Mn4fP{dmLx8LFLR6DOEXoY83Fct=4mT8DH?atruOT7yg?>;VanEUzR- zxTkueOC&Jw3fENn_rWsis$*G#@*<=g3CUPIC{k0_#sri^&gioNMZbV*%zlc9cOFzl zMrdfaT>=G`6{fA3dUZaEDA|SI#EnpOY*0uOrj*Y+1OxY72QN?u{+kHHa|)%vJtZkbeUGbCEJ?)t<#55hV8Kx*HtP zpr!6SkKz6`SrR>fRr`)D2S{OJ{;(^L56dYR@W#Ckb|dgec_4;|QlJPVQ`_W=Q**(0 z*gsy`3R2c(PaoUO+P$El5;2vrHZhrTWpwjJU8q4D*R z=bPCv$(C_Tr)Cpp>Ep5gwm%~xp6nNQ@v0@g#G|G$<4+}flnR4+pbQXN{s-QD$2FZy zC_H9S2Qxjk+wj)9b<~KWTi3vww5oAS0M4IwXK@L_V6K?e-rm(%T@8S{4G+sOrh0H? zKGbw9CnvGvZHWDtGnH9DYXwY}_2LuLXoY=Ay{5&!wS!0C)X~axgPlOsrVp#>HY+N7;G$&UN4fV|-(R`c%y* z4h_Neg>w~z{8!`JLzh`(yB-2t@;?0fx}wV_jF<+t|wNUACk6ri~ObqXNE>t2bSSB|#mRDyWomHgpE=Kc-ycjLw1l#WhDNrXBsIWOa69V`+B*7(OYBk6 z@-^Qa7-h?}Cs+^8`4rxXZ}hTMtn@+Q`14Ifl09taq}Ad!O_ZK^vL5&K@EX_PpYp}* zUc>_MPcfw3eieYGO|>lu_`$E%pq=&ptag95e(%c#P zYwli5AP+WUtj`=X6$xOnTpv-XvH$6MBW06r&wUM%MTTFlSTl^RIph@6`4s;?c8S|d zga||drG9N-&dfcN^L*-G5`U@q98=rasP+&6=gk{}u5MDJ)LUGfrcvCp(%Ij|<<)C` z##ItEv=0c6)i;|w#`Y_61;@F<4wN#Hq4}!jmgG1{7^}qnn^?Jp!msJ{9!guUG<`Hw zpNZ+`8+*A{Hf!b2zR-sq=IYy|yD(uNu|fTYNm+iWi)U{tHH^ID!)QrF-TIbJv9|j( zuut)Xv87T5W7l~So?l%#lj}2QGCE_s(GFWR4!FbpL3XDHw&Y^T{{nw}*Dvhji@&;q z6LFQ8oHKi`!@|zjIElG2+lqqe>qV?UayGE!Q0`+xg3ynlO<^h1lEW&ow!eo+U3){A z%!H#8d{r*^@C`V9Gq_Z1_6Ky5rbeV!Z diff --git a/public/js/app.js b/public/js/app.js index 4dd9e901ced619ce6c1f590438f08a95f37a00e9..b5f3c56253be06589d17a5f74325ec86ee6d1dac 100644 GIT binary patch delta 15905 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

^htD)e(&?RHr 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 SE)Z??-Lh~QeeZ7hvi}Qc&#boq delta 13133 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 I^NGdn0GY%OC;$Ke delta 53 zcmeyx_=|CZig0qWd6I#-rG;UtMUuIBszFMU!9;Tn5p(mDG$V^7BNG!#12Yq|R8xaw Ii;2bU0JaDZxc~qF diff --git a/resources/assets/js/bootstrap.js b/resources/assets/js/bootstrap.js index 6d3eb91b6..4f95a589c 100644 --- a/resources/assets/js/bootstrap.js +++ b/resources/assets/js/bootstrap.js @@ -22,6 +22,7 @@ try { require('./components/commentform'); require('./components/searchform'); require('./components/bookmarkform'); + require('./components/statusform'); } catch (e) {} /** diff --git a/resources/assets/js/components/statusform.js b/resources/assets/js/components/statusform.js new file mode 100644 index 000000000..636afbca5 --- /dev/null +++ b/resources/assets/js/components/statusform.js @@ -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 = ''; + 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); + }); + +}); \ No newline at end of file diff --git a/resources/assets/sass/app.scss b/resources/assets/sass/app.scss index a9369498b..88a18d470 100644 --- a/resources/assets/sass/app.scss +++ b/resources/assets/sass/app.scss @@ -11,6 +11,8 @@ @import "custom"; +@import "components/filters"; + @import "components/typeahead"; @import "components/notifications"; diff --git a/resources/assets/sass/components/filters.scss b/resources/assets/sass/components/filters.scss new file mode 100644 index 000000000..99d026a49 --- /dev/null +++ b/resources/assets/sass/components/filters.scss @@ -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; +} \ No newline at end of file diff --git a/resources/assets/sass/custom.scss b/resources/assets/sass/custom.scss index 551d2571f..6b04d2ba2 100644 --- a/resources/assets/sass/custom.scss +++ b/resources/assets/sass/custom.scss @@ -234,3 +234,18 @@ body, button, input, textarea { height: 32px; background-position: 50%; } + +@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; +} \ No newline at end of file diff --git a/resources/views/profile/show.blade.php b/resources/views/profile/show.blade.php index d9fa85c54..525f24d18 100644 --- a/resources/views/profile/show.blade.php +++ b/resources/views/profile/show.blade.php @@ -27,7 +27,7 @@ @foreach($timeline as $status)

-
+
diff --git a/resources/views/timeline/partial/new-form.blade.php b/resources/views/timeline/partial/new-form.blade.php index 37811d6a3..77425e2d5 100644 --- a/resources/views/timeline/partial/new-form.blade.php +++ b/resources/views/timeline/partial/new-form.blade.php @@ -1,13 +1,20 @@
New Post
+ @if (session('error')) +
+ {{ session('error') }} +
+ @endif @csrf + +
- + - 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.
@@ -17,17 +24,52 @@ Max length: {{config('pixelfed.max_caption_length')}} characters.
- {{--
- -
- - +
+ +
+ +
+ +
+ + +
+ + Please mark all NSFW and controversial content, as per our content policy. + +
+ +{{--
+ +
+ + +
+ + Toggle this to limit this post to your followers only. + +
--}} + +
+ +
+ +
+ + No filter selected. + +
+
+ + +
- - Please mark all NSFW and controversial content, as per our content policy. - -
--}} +
-
\ No newline at end of file +
From faec46069bc9b94239f25209378f7e330c8d0f4a Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 13 Jun 2018 21:29:20 -0600 Subject: [PATCH 22/27] Update StatusDelete Pipeline --- app/Jobs/StatusPipeline/StatusDelete.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/Jobs/StatusPipeline/StatusDelete.php b/app/Jobs/StatusPipeline/StatusDelete.php index 30aecd7e2..f48b200a3 100644 --- a/app/Jobs/StatusPipeline/StatusDelete.php +++ b/app/Jobs/StatusPipeline/StatusDelete.php @@ -58,6 +58,14 @@ 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') From a415b421cbc89e6d2cc63dc650f6256304f75127 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 13 Jun 2018 23:30:43 -0600 Subject: [PATCH 23/27] Add Email Verification --- app/EmailVerification.php | 15 +++++++ app/Http/Controllers/AccountController.php | 45 ++++++++++++++++++- app/Http/Kernel.php | 1 + .../Middleware/EmailVerificationCheck.php | 28 ++++++++++++ app/Mail/ConfirmEmail.php | 34 ++++++++++++++ config/pixelfed.php | 10 +++++ ...41422_create_email_verifications_table.php | 35 +++++++++++++++ .../views/account/verify_email.blade.php | 24 ++++++++++ .../views/emails/confirm_email.blade.php | 12 +++++ routes/web.php | 5 ++- 10 files changed, 206 insertions(+), 3 deletions(-) create mode 100644 app/EmailVerification.php create mode 100644 app/Http/Middleware/EmailVerificationCheck.php create mode 100644 app/Mail/ConfirmEmail.php create mode 100644 database/migrations/2018_06_14_041422_create_email_verifications_table.php create mode 100644 resources/views/account/verify_email.blade.php create mode 100644 resources/views/emails/confirm_email.blade.php diff --git a/app/EmailVerification.php b/app/EmailVerification.php new file mode 100644 index 000000000..cdc9b8bb1 --- /dev/null +++ b/app/EmailVerification.php @@ -0,0 +1,15 @@ +user_token . '/' . $this->random_token; + return "{$base}{$path}"; + } +} diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 6f5eeea43..999f6b711 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -4,8 +4,9 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; use Carbon\Carbon; -use Auth, Cache, Redis; -use App\{Notification, Profile, User}; +use App\Mail\ConfirmEmail; +use Auth, DB, Cache, Mail, Redis; +use App\{EmailVerification, Notification, Profile, User}; class AccountController extends Controller { @@ -30,6 +31,46 @@ class AccountController extends Controller 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"; diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 52a072844..61e44822f 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -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, ]; } diff --git a/app/Http/Middleware/EmailVerificationCheck.php b/app/Http/Middleware/EmailVerificationCheck.php new file mode 100644 index 000000000..04ee1fb1b --- /dev/null +++ b/app/Http/Middleware/EmailVerificationCheck.php @@ -0,0 +1,28 @@ +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); + } +} diff --git a/app/Mail/ConfirmEmail.php b/app/Mail/ConfirmEmail.php new file mode 100644 index 000000000..83191f5fe --- /dev/null +++ b/app/Mail/ConfirmEmail.php @@ -0,0 +1,34 @@ +verify = $verify; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + return $this->markdown('emails.confirm_email')->with(['verify'=>$this->verify]); + } +} diff --git a/config/pixelfed.php b/config/pixelfed.php index a3ec46783..c825643a7 100644 --- a/config/pixelfed.php +++ b/config/pixelfed.php @@ -106,5 +106,15 @@ return [ | */ '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), ]; \ No newline at end of file diff --git a/database/migrations/2018_06_14_041422_create_email_verifications_table.php b/database/migrations/2018_06_14_041422_create_email_verifications_table.php new file mode 100644 index 000000000..cbcc6ae3a --- /dev/null +++ b/database/migrations/2018_06_14_041422_create_email_verifications_table.php @@ -0,0 +1,35 @@ +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'); + } +} diff --git a/resources/views/account/verify_email.blade.php b/resources/views/account/verify_email.blade.php new file mode 100644 index 000000000..99ae26f3c --- /dev/null +++ b/resources/views/account/verify_email.blade.php @@ -0,0 +1,24 @@ +@extends('layouts.app') + +@section('content') +
+
+ @if (session('status')) +
+ {{ session('status') }} +
+ @endif +
+
Confirm Email Address
+
+

You need to confirm your email address ({{Auth::user()->email}}) before you can proceed.

+
+
+ @csrf + +
+
+
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/emails/confirm_email.blade.php b/resources/views/emails/confirm_email.blade.php new file mode 100644 index 000000000..20d388b96 --- /dev/null +++ b/resources/views/emails/confirm_email.blade.php @@ -0,0 +1,12 @@ +@component('mail::message') +# Email Confirmation + +Please confirm your email address. + +@component('mail::button', ['url' => $verify->url()]) +Confirm Email +@endcomponent + +Thanks,
+{{ config('app.name') }} +@endcomponent diff --git a/routes/web.php b/routes/web.php index 160d9bd6b..eb9fe2ad1 100644 --- a/routes/web.php +++ b/routes/web.php @@ -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'); From 0be5a9ec5d1ac32e3282703720faa4dfbbfe1353 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 13 Jun 2018 23:36:21 -0600 Subject: [PATCH 24/27] Update compiled assets --- public/js/app.js | Bin 309793 -> 309837 bytes public/mix-manifest.json | Bin 250 -> 250 bytes resources/assets/js/components/commentform.js | 2 ++ 3 files changed, 2 insertions(+) diff --git a/public/js/app.js b/public/js/app.js index b5f3c56253be06589d17a5f74325ec86ee6d1dac..f24ff355008c7cce42088ed18dcedae84c2847bb 100644 GIT binary patch delta 76 zcmZ4ZMd<7op@uDt4nM>)^$Lpe3pA8cGK&+Fa#B;2bQBFVb+$YFVEoG{s)I$=u-)bt OBM>ufxB12VbUy%d7afKG delta 31 lcmX^6MQGs{p@uDt4nMYs{b2md*q-?dgqgNy{$hTz9{>nS5Q6{! diff --git a/public/mix-manifest.json b/public/mix-manifest.json index ba69dabfd26441d619899336861ac775b281b86a..e132fcbe8fb7e7b22a5247e1663b9ca943f4cc2e 100644 GIT binary patch delta 30 lcmeyx_=|CZvWTHUl2MYOp+%};Vxozefw`HHQOZQ~!vK`M31I*L delta 30 lcmeyx_=|CZvWT&{skxcCL0XcriGhKorAcy Date: Wed, 13 Jun 2018 23:37:45 -0600 Subject: [PATCH 25/27] Update nav --- resources/views/layouts/partial/nav.blade.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/views/layouts/partial/nav.blade.php b/resources/views/layouts/partial/nav.blade.php index b2280fa57..29e3e63c6 100644 --- a/resources/views/layouts/partial/nav.blade.php +++ b/resources/views/layouts/partial/nav.blade.php @@ -6,11 +6,13 @@
+@auth +@endauth \ No newline at end of file From aa32b8020cbd78a29157a670d2fd0a636c07db9c Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Thu, 14 Jun 2018 01:42:47 -0600 Subject: [PATCH 26/27] Update status template --- app/Http/Controllers/AccountController.php | 6 +++--- resources/views/status/template.blade.php | 8 +------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 999f6b711..9f03ef728 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -41,7 +41,7 @@ class AccountController extends Controller 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); @@ -60,8 +60,8 @@ class AccountController extends Controller public function confirmVerifyEmail(Request $request, $userToken, $randomToken) { - $verify = EmailVerification::where(DB::raw('BINARY `user_token`'), $userToken) - ->where(DB::raw('BINARY `random_token`'), $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()); diff --git a/resources/views/status/template.blade.php b/resources/views/status/template.blade.php index 7a3910887..baf37c296 100644 --- a/resources/views/status/template.blade.php +++ b/resources/views/status/template.blade.php @@ -74,7 +74,7 @@
@if($item->comments()->count() > 3) @endif
@@ -93,12 +93,6 @@

@else - @foreach($item->comments->reverse()->take(3) as $comment) -

- {{$comment->profile->username}} - {!! str_limit($item->rendered ?? e($item->caption), 150) !!} -

- @endforeach @endif
From 56b18f3e08801dd6f4071eceae06d531a0a18c7c Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Thu, 14 Jun 2018 20:54:05 -0600 Subject: [PATCH 27/27] Update ImageOptimizePipeline, do not optimize gifs --- app/Jobs/ImageOptimizePipeline/ImageUpdate.php | 5 ++++- app/Util/Media/Image.php | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/Jobs/ImageOptimizePipeline/ImageUpdate.php b/app/Jobs/ImageOptimizePipeline/ImageUpdate.php index fab0975ba..5b21ea7e9 100644 --- a/app/Jobs/ImageOptimizePipeline/ImageUpdate.php +++ b/app/Jobs/ImageOptimizePipeline/ImageUpdate.php @@ -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; } diff --git a/app/Util/Media/Image.php b/app/Util/Media/Image.php index db7641fd3..3f67d43f5 100644 --- a/app/Util/Media/Image.php +++ b/app/Util/Media/Image.php @@ -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();