Favour redirects over re-using the same paths

I was re-using the same paths for a bunch of stuff in order to
minimise redirects (POSTing new statuses to the timeline, or performing
actions on a status), but then this breaks the behaviour of the
browser's refresh button. I've moved all those actions to their
own paths, which helps break up the code, makes the URLs more
semantic, and lets you use the refresh button without accidentally
performing an action.

This is at the expense of an additional HTTP request, but I've
tried to minimise the cost by passing through the status from the
previous action so we don't have to requery for it on the server
side.
This commit is contained in:
St John Karp 2018-08-26 14:34:01 -07:00
parent 96cb4ffcc6
commit 0247f8b57e
5 changed files with 127 additions and 91 deletions

View File

@ -4,48 +4,24 @@ namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Mastodon;
use GuzzleHttp\Psr7;
use Illuminate\Http\Request;
class StatusController extends Controller
{
public function show_status(Request $request, string $status_id)
{
// The user has a session and may be here to favourite/unfavourite
// a status.
if (session()->has('user') && $request->has('action'))
if (session()->has('status'))
{
$user = session('user');
if ($request->action === 'favourite')
{
$status = Mastodon::domain(env('MASTODON_DOMAIN'))
->token($user->token)
->post('/statuses/' . $status_id . '/favourite');
}
elseif ($request->action === 'unfavourite')
{
$status = Mastodon::domain(env('MASTODON_DOMAIN'))
->token($user->token)
->post('/statuses/' . $status_id . '/unfavourite');
}
elseif ($request->action === 'reblog')
{
$status = Mastodon::domain(env('MASTODON_DOMAIN'))
->token($user->token)
->post('/statuses/' . $status_id . '/reblog');
}
elseif ($request->action === 'unreblog')
{
$status = Mastodon::domain(env('MASTODON_DOMAIN'))
->token($user->token)
->post('/statuses/' . $status_id . '/unreblog');
}
// The user is coming here after peforming an action on a status,
// in which case we don't need to re-query it.
$status = session('status');
}
// If the status hasn't been returned from performing an action on it,
// we need to query for it.
if (!isset($session))
else
{
// If the status hasn't been returned from performing an action,
// we need to query for it.
$status = Mastodon::domain(env('MASTODON_DOMAIN'))
->get('/statuses/' . $status_id);
}
@ -59,6 +35,92 @@ class StatusController extends Controller
return view('show_status', $vars);
}
public function reblog_status(Request $request, string $status_id)
{
$user = session('user');
$status = Mastodon::domain(env('MASTODON_DOMAIN'))
->token($user->token)
->post('/statuses/' . $status_id . '/reblog');
return redirect()->route('status', ['status_id' => $status_id])
->with('status', $status);
}
public function unreblog_status(Request $request, string $status_id)
{
$user = session('user');
$status = Mastodon::domain(env('MASTODON_DOMAIN'))
->token($user->token)
->post('/statuses/' . $status_id . '/unreblog');
return redirect()->route('status', ['status_id' => $status_id])
->with('status', $status);
}
public function favourite_status(Request $request, string $status_id)
{
$user = session('user');
$status = Mastodon::domain(env('MASTODON_DOMAIN'))
->token($user->token)
->post('/statuses/' . $status_id . '/favourite');
return redirect()->route('status', ['status_id' => $status_id])
->with('status', $status);
}
public function unfavourite_status(Request $request, string $status_id)
{
$user = session('user');
$status = Mastodon::domain(env('MASTODON_DOMAIN'))
->token($user->token)
->post('/statuses/' . $status_id . '/unfavourite');
return redirect()->route('status', ['status_id' => $status_id])
->with('status', $status);
}
public function post_status(Request $request)
{
$user = session('user');
# Verify we have an actual status to post.
if (!$request->has('status'))
{
abort(400);
}
$params = [
'status' => $request->status
];
$inputs = [
'in_reply_to_id',
'media_ids',
'sensitive',
'spoiler_text',
'visibility',
'language'
];
foreach ($inputs as $input)
{
if ($request->has($input))
{
$params[$input] = $request->input($input);
}
}
$new_status = Mastodon::domain(env('MASTODON_DOMAIN'))
->token($user->token)
->post('/statuses', $params);
return redirect()->route('home');
}
public function context(Request $request, string $status_id)
{
$status = Mastodon::domain(env('MASTODON_DOMAIN'))

View File

@ -44,42 +44,4 @@ class TimelineController extends Controller
return view('home_timeline', $vars);
}
public function post_status(Request $request)
{
$user = session('user');
# Verify we have an actual status to post.
if (!$request->has('status'))
{
abort(400);
}
$params = [
'status' => $request->status
];
$inputs = [
'in_reply_to_id',
'media_ids',
'sensitive',
'spoiler_text',
'visibility',
'language'
];
foreach ($inputs as $input)
{
if ($request->has($input))
{
$params[$input] = $request->input($input);
}
}
$new_status = Mastodon::domain(env('MASTODON_DOMAIN'))
->token($user->token)
->post('/statuses', $params);
return redirect()->route('home');
}
}

View File

@ -19,7 +19,7 @@
@endcomponent
@if ($logged_in)
<form method="post" action="/timeline/home">
<form method="post" action="/status">
<input
type="text"
name="spoiler_text"

View File

@ -34,10 +34,10 @@
<span title="Reblog">
@if ($status['reblogged'])
<span class="reblogged">
<a href="/status/{{ $status['id'] }}?action=unreblog">&#8634;</a>
<a href="/status/{{ $status['id'] }}/unreblog">&#8634;</a>
</span>
@else
<a href="/status/{{ $status['id'] }}?action=reblog">&#8634;</a>
<a href="/status/{{ $status['id'] }}/reblog">&#8634;</a>
@endif
{{ $status['reblogs_count'] }}
</span>
@ -46,10 +46,10 @@
<span title="Favourite">
@if ($status['favourited'])
<span class="favourited">
<a href="/status/{{ $status['id'] }}?action=unfavourite">&#9733;</a>
<a href="/status/{{ $status['id'] }}/unfavourite">&#9733;</a>
</span>
@else
<a href="/status/{{ $status['id'] }}?action=favourite">&#9734;</a>
<a href="/status/{{ $status['id'] }}/favourite">&#9734;</a>
@endif
{{ $status['favourites_count'] }}
</span>

View File

@ -12,36 +12,48 @@
*/
Route::get('/', function() {
if (!session()->has('user'))
if (!session()->has('user'))
{
return redirect()->route('public');
}
else
{
return redirect()->route('home');
}
else
{
return redirect()->route('home');
}
});
Route::get('/timeline/public', 'TimelineController@public_timeline')
->name('public');
->name('public');
Route::get('/timeline/home', 'TimelineController@home_timeline')
->name('home')
->middleware('authorize');
Route::post('/timeline/home', 'TimelineController@post_status')
->middleware('authorize');
->name('home')
->middleware('authorize');
Route::get('/status/{status_id}', 'StatusController@show_status')
->name('status');
->name('status');
Route::get('/status/{status_id}/reblog', 'StatusController@reblog_status')
->middleware('authorize');
Route::get('/status/{status_id}/unreblog', 'StatusController@unreblog_status')
->middleware('authorize');
Route::get('/status/{status_id}/favourite', 'StatusController@favourite_status')
->middleware('authorize');
Route::get('/status/{status_id}/unfavourite', 'StatusController@unfavourite_status')
->middleware('authorize');
Route::get('/status/{status_id}/thread', 'StatusController@context');
Route::post('/status', 'StatusController@post_status')
->middleware('authorize');
Route::get('/notifications', 'NotificationsController@get_notifications')
->name('notifications')
->middleware('authorize');
->name('notifications')
->middleware('authorize');
Route::get('/login', 'LoginController@login')
->name('login');
->name('login');
Route::get('/callback', 'LoginController@callback');