Skip to content

Commit 5e71d23

Browse files
authored
Merge pull request #11954 from nanaya/turbo-error-handling
Show session verification box for turbo requests
2 parents 21fc56c + 30ccd6c commit 5e71d23

File tree

5 files changed

+49
-20
lines changed

5 files changed

+49
-20
lines changed

app/Libraries/SessionVerification/Controller.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ public static function initiate()
2828
return response(null, $statusCode);
2929
}
3030

31-
if (\Request::ajax()) {
31+
$request = \Request::instance();
32+
if ($request->ajax() || ($request->getMethod() !== 'GET' && is_turbo_request($request))) {
3233
return response([
3334
'authentication' => 'verify',
3435
'box' => view(
3536
'users._verify_box',
3637
compact('email')
3738
)->render(),
38-
], $statusCode);
39+
], $statusCode, ['x-turbo-action' => 'session-verification']);
3940
}
4041

4142
return ext_view('users.verify', compact('email'), null, $statusCode);

app/helpers.php

+9-2
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,13 @@ function is_json_request(): bool
852852
return is_api_request() || Request::expectsJson();
853853
}
854854

855+
function is_turbo_request(?HttpRequest $request = null): bool
856+
{
857+
$request ??= Request::instance();
858+
859+
return $request->headers->get('x-turbo-request-id') !== null;
860+
}
861+
855862
function is_valid_email_format(?string $email): bool
856863
{
857864
if ($email === null) {
@@ -938,14 +945,14 @@ function ujs_redirect($url, $status = 200)
938945
$request = Request::instance();
939946
// This is done mainly to work around fetch ignoring/removing anchor from page redirect.
940947
// Reference: https://github.com/hotwired/turbo/issues/211
941-
if ($request->headers->get('x-turbo-request-id') !== null) {
948+
if (is_turbo_request($request)) {
942949
if ($status === 200 && $request->getMethod() !== 'GET') {
943950
// Turbo doesn't like 200 response on non-GET requests.
944951
// Reference: https://github.com/hotwired/turbo/issues/22
945952
$status = 201;
946953
}
947954

948-
return response($url, $status, ['content-type' => 'text/osu-turbo-redirect']);
955+
return response($url, $status, ['x-turbo-action' => 'redirect']);
949956
} elseif ($request->ajax() && $request->getMethod() !== 'GET') {
950957
return ext_view('layout.ujs-redirect', compact('url'), 'js', $status);
951958
} else {

resources/js/core/user/user-verification.ts

+24
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
22
// See the LICENCE file in the repository root for full licence text.
33

4+
import { type FetchResponse, type TurboSubmitEndEvent } from '@hotwired/turbo';
45
import { route } from 'laroute';
56
import core from 'osu-core-singleton';
67
import { xhrErrorMessage } from 'utils/ajax';
@@ -77,6 +78,8 @@ export default class UserVerification {
7778
.on('click', '.js-user-verification--reissue', this.reissue);
7879
$.subscribe('user-verification:success', this.success);
7980

81+
document.addEventListener('turbo:submit-end', this.onErrorTurbo);
82+
8083
$(window).on('resize scroll', this.reposition);
8184
}
8285

@@ -140,6 +143,27 @@ export default class UserVerification {
140143
this.showOnError(xhr, createClickCallback(e.target))
141144
);
142145

146+
private readonly onErrorTurbo = (e: TurboSubmitEndEvent) => {
147+
// Workaround wrong definition (the field always exists).
148+
if (!('fetchResponse' in e.detail)) {
149+
return;
150+
}
151+
152+
const fetchResponse = e.detail.fetchResponse as FetchResponse | undefined;
153+
if (fetchResponse == null || fetchResponse.header('x-turbo-action') !== 'session-verification') {
154+
return;
155+
}
156+
157+
e.preventDefault();
158+
const form = e.detail.formSubmission.formElement;
159+
fetchResponse.responseText.then((jsonString: string) => {
160+
const json = JSON.parse(jsonString) as UserVerificationJson;
161+
this.show(json.box, () => {
162+
form.requestSubmit();
163+
});
164+
});
165+
};
166+
143167
private readonly prepareForRequest = (type: string) => {
144168
this.request?.abort();
145169
this.setMessage(trans(`user_verification.box.${type}`), true);

resources/js/setup-turbo.ts

+12-14
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,19 @@ document.addEventListener('turbo:submit-end', (e) => {
2525
});
2626

2727
document.addEventListener('turbo:before-fetch-response', (e) => {
28-
if (!e.detail.fetchResponse.contentType?.match(/^text\/osu-turbo-redirect[ ;]*/)) {
29-
return;
28+
if (e.detail.fetchResponse.header('x-turbo-action') === 'redirect') {
29+
e.preventDefault();
30+
e.detail.fetchResponse.responseText.then((url) => {
31+
const [currentUrlBase, urlBase] = [document.location.href, url].map((u) => u.replace(/#.*/, ''));
32+
33+
if (currentUrlBase === urlBase) {
34+
// a normal/advance visit to same url won't reload the page
35+
Turbo.visit(url, { action: 'replace' });
36+
} else {
37+
Turbo.visit(url);
38+
}
39+
});
3040
}
31-
32-
e.preventDefault();
33-
e.detail.fetchResponse.responseText.then((url) => {
34-
const [currentUrlBase, urlBase] = [document.location.href, url].map((u) => u.replace(/#.*/, ''));
35-
36-
if (currentUrlBase === urlBase) {
37-
// a normal/advance visit to same url won't reload the page
38-
Turbo.visit(url, { action: 'replace' });
39-
} else {
40-
Turbo.visit(url);
41-
}
42-
});
4341
});
4442

4543
// disable turbo navigation for old webs

resources/views/teams/show.blade.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,8 @@ class="team-action-button team-action-button--join-cancel"
104104
@endphp
105105
<form
106106
action="{{ route('teams.applications.store', ['team' => $team]) }}"
107-
data-confirm="{{ osu_trans('common.confirmation') }}"
107+
data-turbo-confirm="{{ osu_trans('common.confirmation') }}"
108108
data-reload-on-success="1"
109-
data-remote="1"
110109
method="POST"
111110
title="{{ $joinPriv->message() }}"
112111
>

0 commit comments

Comments
 (0)