planiverse

A minimalist, no-JS front-end for Mastodon.
git clone https://git.stjo.hn/planiverse
Log | Files | Refs | README | LICENSE

commit d8c1ed68840b5caf6c94d890a2e10a2ceac45345
parent 7e617469ccc104acd1e355be2f8e90a8f26b0c19
Author: St John Karp <stjohn@fuzzjunket.com>
Date:   Sat, 25 Aug 2018 17:29:36 -0700

Implement notifications page

Created a new page that displays notifications and added it to the
global nav. Abstracted out the pagination methods from the timeline
controller and put it in a helper class. Abstracted out the event info
(account, timestamp, etc.) into its own component.

Diffstat:
Aapp/Helpers/Pagination.php | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapp/Http/Controllers/NotificationsController.php | 29+++++++++++++++++++++++++++++
Mapp/Http/Controllers/TimelineController.php | 62+++++---------------------------------------------------------
Mpublic/css/styles.css | 2+-
Aresources/views/account_time_info.blade.php | 19+++++++++++++++++++
Mresources/views/navigation.blade.php | 1+
Aresources/views/notification.blade.php | 24++++++++++++++++++++++++
Aresources/views/notifications.blade.php | 26++++++++++++++++++++++++++
Mresources/views/status.blade.php | 25++++++-------------------
Mroutes/web.php | 4++++
10 files changed, 177 insertions(+), 77 deletions(-)

diff --git a/app/Helpers/Pagination.php b/app/Helpers/Pagination.php @@ -0,0 +1,62 @@ +<?php + +namespace App\Helpers; + +use Mastodon; +use GuzzleHttp\Psr7; +use Illuminate\Http\Request; + +class Pagination +{ + public static function compile_links(string $route) + { + $links = [ + 'next' => null, + 'prev' => null + ]; + + # Parse out the links header returned from the Mastodon API. + $links_header = Mastodon::getResponse()->getHeader('link'); + foreach (Psr7\parse_header($links_header) as $link) + { + # Find the prev and next links. + if ($link['rel'] === 'prev' || $link['rel'] === 'next') + { + $url = parse_url(trim($link[0], '<>')); + foreach (explode('&', $url['query']) as $query_param) + { + # Grab the ID query parameters from the link. + if (strpos($query_param, 'max_id=') === 0 + || strpos($query_param, 'since_id=') === 0) + { + # Construct new links with the correct offset. + $links[$link['rel']] = route($route) . '?' . $query_param; + } + } + } + } + + return $links; + } + + public static function compile_params(Request $request) + { + $params = []; + + if ($request->has('max_id') && $request->has('since_id')) + { + # This scenario makes no sense. Someone's trying to dicker with the URL. + abort(400); + } + elseif ($request->has('max_id')) + { + $params['max_id'] = $request->max_id; + } + elseif ($request->has('since_id')) + { + $params['since_id'] = $request->since_id; + } + + return $params; + } +} diff --git a/app/Http/Controllers/NotificationsController.php b/app/Http/Controllers/NotificationsController.php @@ -0,0 +1,29 @@ +<?php + +namespace App\Http\Controllers; + +use App\Http\Controllers\Controller; +use Mastodon; +use Illuminate\Http\Request; +use App\Helpers\Pagination; + +class NotificationsController extends Controller +{ + public function get_notifications(Request $request) + { + $user = session('user'); + $params = Pagination::compile_params($request); + + $notifications = Mastodon::domain(env('MASTODON_DOMAIN')) + ->token($user->token) + ->get('/notifications', $params); + + $vars = [ + 'notifications' => $notifications, + 'mastodon_domain' => explode('//', env('MASTODON_DOMAIN'))[1], + 'links' => Pagination::compile_links('notifications') + ]; + + return view('notifications', $vars); + } +} diff --git a/app/Http/Controllers/TimelineController.php b/app/Http/Controllers/TimelineController.php @@ -4,14 +4,14 @@ namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Mastodon; -use GuzzleHttp\Psr7; use Illuminate\Http\Request; +use App\Helpers\Pagination; class TimelineController extends Controller { public function public_timeline(Request $request) { - $params = $this->compile_params($request); + $params = Pagination::compile_params($request); $params['local'] = true; $timeline = Mastodon::domain(env('MASTODON_DOMAIN')) @@ -20,7 +20,7 @@ class TimelineController extends Controller $vars = [ 'statuses' => $timeline, 'mastodon_domain' => explode('//', env('MASTODON_DOMAIN'))[1], - 'links' => $this->compile_links('public') + 'links' => Pagination::compile_links('public') ]; return view('public_timeline', $vars); @@ -30,7 +30,7 @@ class TimelineController extends Controller { $user = session('user'); - $params = $this->compile_params($request); + $params = Pagination::compile_params($request); $timeline = Mastodon::domain(env('MASTODON_DOMAIN')) ->token($user->token) @@ -39,7 +39,7 @@ class TimelineController extends Controller $vars = [ 'statuses' => $timeline, 'mastodon_domain' => explode('//', env('MASTODON_DOMAIN'))[1], - 'links' => $this->compile_links('home') + 'links' => Pagination::compile_links('home') ]; return view('home_timeline', $vars); @@ -82,56 +82,4 @@ class TimelineController extends Controller return redirect()->route('home'); } - - private function compile_links(string $route) - { - $links = [ - 'next' => null, - 'prev' => null - ]; - - # Parse out the links header returned from the Mastodon API. - $links_header = Mastodon::getResponse()->getHeader('link'); - foreach (Psr7\parse_header($links_header) as $link) - { - # Find the prev and next links. - if ($link['rel'] === 'prev' || $link['rel'] === 'next') - { - $url = parse_url(trim($link[0], '<>')); - foreach (explode('&', $url['query']) as $query_param) - { - # Grab the ID query parameters from the link. - if (strpos($query_param, 'max_id=') === 0 - || strpos($query_param, 'since_id=') === 0) - { - # Construct new links with the correct offset. - $links[$link['rel']] = route($route) . '?' . $query_param; - } - } - } - } - - return $links; - } - - private function compile_params(Request $request) - { - $params = []; - - if ($request->has('max_id') && $request->has('since_id')) - { - # This scenario makes no sense. Someone's trying to dicker with the URL. - abort(400); - } - elseif ($request->has('max_id')) - { - $params['max_id'] = $request->max_id; - } - elseif ($request->has('since_id')) - { - $params['since_id'] = $request->since_id; - } - - return $params; - } } diff --git a/public/css/styles.css b/public/css/styles.css @@ -71,7 +71,7 @@ div.actions span.reblogged a { color: green; } -time { +time, span.action-notification { font-size: smaller; margin-left: 1em; } diff --git a/resources/views/account_time_info.blade.php b/resources/views/account_time_info.blade.php @@ -0,0 +1,19 @@ +<span title="{{ $account['acct'] }}"> + <a href="{{ $account['url'] }}"> + <img + src="{{ $account['avatar'] }}" + alt="{{ $account['acct'] }}" + class="avatar" + /> + {{ $account['display_name'] }} + </a> +</span> +<time datetime="{{ $created_at }}"> + @php + $created_at_datetime = new Carbon\Carbon($created_at); + @endphp + @if (env('SHOW_BEATS') === true) + {{ '@' . $created_at_datetime->format('B') }} | + @endif + {{ $created_at_datetime->diffForHumans(null, false, true) }} +</time> diff --git a/resources/views/navigation.blade.php b/resources/views/navigation.blade.php @@ -2,5 +2,6 @@ <ul> <li><a href="/timeline/home">Timeline</a></li> <li><a href="/timeline/public">Public Timeline</a></li> + <li><a href="/notifications">Notifications</a></li> </ul> </nav> diff --git a/resources/views/notification.blade.php b/resources/views/notification.blade.php @@ -0,0 +1,24 @@ +<article> + @component('account_time_info', [ + 'account' => $notification['account'], + 'created_at' => $notification['created_at'] + ]) + @endcomponent + + <span class="action-notification"> + @if ($notification['type'] === 'mention') + mentioned + @elseif ($notification['type'] === 'reblog') + reblogged + @elseif ($notification['type'] === 'favourite') + favourited + @elseif ($notification['type'] === 'follow') + followed you. + @endif + </span> + + @if ($notification['status'] ?? null !== null) + @component('status', ['status' => $notification['status']]) + @endcomponent + @endif +</article> diff --git a/resources/views/notifications.blade.php b/resources/views/notifications.blade.php @@ -0,0 +1,26 @@ +<!doctype html> +<html lang="{{ app()->getLocale() }}"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + + <title>{{ $mastodon_domain }} | Notifications</title> + + <link rel="stylesheet" href="/css/styles.css" /> + </head> + <body> + <h1>{{ $mastodon_domain }} | Notifications</h1> + + @component('navigation') + @endcomponent + + @foreach ($notifications as $notification) + @component('notification', ['notification' => $notification]) + @endcomponent + @endforeach + + @component('pagination', ['links' => $links]) + @endcomponent + </body> +</html> diff --git a/resources/views/status.blade.php b/resources/views/status.blade.php @@ -1,24 +1,11 @@ <hr /> <article> - <span title="{{ $status['account']['acct'] }}"> - <a href="{{ $status['account']['url'] }}"> - <img - src="{{ $status['account']['avatar'] }}" - alt="{{ $status['account']['acct'] }}" - class="avatar" - /> - {{ $status['account']['display_name'] }} - </a> - </span> - <time datetime="{{ $status['created_at'] }}"> - @php - $created_at = new Carbon\Carbon($status['created_at']); - @endphp - @if (env('SHOW_BEATS') === true) - {{ '@' . $created_at->format('B') }} | - @endif - {{ $created_at->diffForHumans(null, false, true) }} - </time> + @component('account_time_info', [ + 'account' => $status['account'], + 'created_at' => $status['created_at'] + ]) + @endcomponent + @if ($status['spoiler_text'] !== '') <details> <summary>{{ $status['spoiler_text'] }}</summary> diff --git a/routes/web.php b/routes/web.php @@ -35,6 +35,10 @@ Route::post('/timeline/home', 'TimelineController@post_status') Route::get('/status/{status_id}', 'StatusController@show_status') ->name('status'); +Route::get('/notifications', 'NotificationsController@get_notifications') + ->name('notifications') + ->middleware('authorize'); + Route::get('/login', 'LoginController@login') ->name('login');