| 
									
										
										
										
											2022-09-29 12:02:41 +02:00
										 |  |  | /* | 
					
						
							|  |  |  | 	GoToSocial | 
					
						
							| 
									
										
										
										
											2023-03-12 18:49:06 +01:00
										 |  |  | 	Copyright (C) GoToSocial Authors admin@gotosocial.org | 
					
						
							|  |  |  | 	SPDX-License-Identifier: AGPL-3.0-or-later | 
					
						
							| 
									
										
										
										
											2022-09-29 12:02:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | 	it under the terms of the GNU Affero General Public License as published by | 
					
						
							|  |  |  | 	the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | 	(at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | 	but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | 	GNU Affero General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  | 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-07 19:48:12 +02:00
										 |  |  | import { SerializedError } from "@reduxjs/toolkit"; | 
					
						
							|  |  |  | import { FetchBaseQueryError } from "@reduxjs/toolkit/query"; | 
					
						
							|  |  |  | import React, { ReactNode } from "react"; | 
					
						
							| 
									
										
										
										
											2022-09-29 12:02:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-18 14:45:14 +01:00
										 |  |  | function ErrorFallback({ error, resetErrorBoundary }) { | 
					
						
							| 
									
										
										
										
											2022-09-29 12:02:41 +02:00
										 |  |  | 	return ( | 
					
						
							|  |  |  | 		<div className="error"> | 
					
						
							|  |  |  | 			<p> | 
					
						
							|  |  |  | 				{"An error occured, please report this on the "} | 
					
						
							|  |  |  | 				<a href="https://github.com/superseriousbusiness/gotosocial/issues">GoToSocial issue tracker</a> | 
					
						
							|  |  |  | 				{" or "} | 
					
						
							|  |  |  | 				<a href="https://matrix.to/#/#gotosocial-help:superseriousbusiness.org">Matrix support room</a>. | 
					
						
							| 
									
										
										
										
											2023-01-18 14:45:14 +01:00
										 |  |  | 				<br />Include the details below: | 
					
						
							| 
									
										
										
										
											2022-09-29 12:02:41 +02:00
										 |  |  | 			</p> | 
					
						
							| 
									
										
										
										
											2023-05-13 12:17:22 +02:00
										 |  |  | 			<div className="details"> | 
					
						
							|  |  |  | 				<pre> | 
					
						
							|  |  |  | 					{error.name}: {error.message} | 
					
						
							|  |  |  | 				</pre> | 
					
						
							|  |  |  | 				<pre> | 
					
						
							|  |  |  | 					{error.stack} | 
					
						
							|  |  |  | 				</pre> | 
					
						
							|  |  |  | 			</div> | 
					
						
							| 
									
										
										
										
											2022-09-29 12:02:41 +02:00
										 |  |  | 			<p> | 
					
						
							|  |  |  | 				<button onClick={resetErrorBoundary}>Try again</button> or <a href="">refresh the page</a> | 
					
						
							|  |  |  | 			</p> | 
					
						
							|  |  |  | 		</div> | 
					
						
							|  |  |  | 	); | 
					
						
							| 
									
										
										
										
											2023-01-18 14:45:14 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-07 19:48:12 +02:00
										 |  |  | interface GtsError { | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * Error message returned from the API. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	error: string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * For OAuth errors: description of the error. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	error_description?: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | interface ErrorProps { | 
					
						
							|  |  |  | 	error: FetchBaseQueryError | SerializedError | Error | undefined; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * Optional function to clear the error. | 
					
						
							|  |  |  | 	 * If provided, rendered error will have | 
					
						
							|  |  |  | 	 * a "dismiss" button. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	reset?: () => void; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-01-18 14:45:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-07 19:48:12 +02:00
										 |  |  | function Error({ error, reset }: ErrorProps) { | 
					
						
							|  |  |  | 	if (error === undefined) { | 
					
						
							|  |  |  | 		return null; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* eslint-disable-next-line no-console */ | 
					
						
							|  |  |  | 	console.error("caught error: ", error); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	let message: ReactNode; | 
					
						
							|  |  |  | 	if ("status" in error) { | 
					
						
							| 
									
										
										
										
											2024-08-27 12:39:26 +02:00
										 |  |  | 		if (typeof error.status === "number") { | 
					
						
							|  |  |  | 			// Error containing GTS API error data.
 | 
					
						
							|  |  |  | 			const gtsError = error.data as GtsError; | 
					
						
							|  |  |  | 			const errMsg = gtsError.error_description ?? gtsError.error; | 
					
						
							|  |  |  | 			message = <>Code {error.status}: {errMsg}</>; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			// RTK Query fetching / parsing / timeout error.
 | 
					
						
							|  |  |  | 			message = <>{error.status}: {error.error}</>; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-01-18 14:45:14 +01:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2024-05-07 19:48:12 +02:00
										 |  |  | 		// SerializedError or Error.
 | 
					
						
							|  |  |  | 		const errMsg = error.message ?? JSON.stringify(error); | 
					
						
							|  |  |  | 		message = ( | 
					
						
							|  |  |  | 			<>{error.name && `${error.name}: `}{errMsg}</> | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	let className = "error"; | 
					
						
							|  |  |  | 	if (reset) { | 
					
						
							|  |  |  | 		className += " with-dismiss"; | 
					
						
							| 
									
										
										
										
											2023-01-18 14:45:14 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ( | 
					
						
							| 
									
										
										
										
											2024-05-07 19:48:12 +02:00
										 |  |  | 		<div className={className}> | 
					
						
							|  |  |  | 			<span>{message}</span> | 
					
						
							|  |  |  | 			{ reset &&  | 
					
						
							|  |  |  | 				<span  | 
					
						
							|  |  |  | 					className="dismiss" | 
					
						
							| 
									
										
										
										
											2024-11-21 14:09:58 +01:00
										 |  |  | 					onClick={(e) => { | 
					
						
							|  |  |  | 						e.preventDefault(); | 
					
						
							|  |  |  | 						e.stopPropagation(); | 
					
						
							|  |  |  | 						reset(); | 
					
						
							|  |  |  | 					}} | 
					
						
							| 
									
										
										
										
											2024-05-07 19:48:12 +02:00
										 |  |  | 					role="button" | 
					
						
							|  |  |  | 					tabIndex={0} | 
					
						
							|  |  |  | 				> | 
					
						
							|  |  |  | 					<span>Dismiss</span> | 
					
						
							|  |  |  | 					<i className="fa fa-fw fa-close" aria-hidden="true" /> | 
					
						
							|  |  |  | 				</span> | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-01-18 14:45:14 +01:00
										 |  |  | 		</div> | 
					
						
							|  |  |  | 	); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-25 18:24:24 +02:00
										 |  |  | export { ErrorFallback, Error }; |