From db784809a4fa126e881a97f34e543b3e448caa5a Mon Sep 17 00:00:00 2001 From: qstokkink Date: Wed, 28 Aug 2024 11:49:30 +0200 Subject: [PATCH] Added an error reporter --- src/tribler/ui/public/locales/en_US.json | 6 +- src/tribler/ui/public/locales/es_ES.json | 6 +- src/tribler/ui/public/locales/pt_BR.json | 6 +- src/tribler/ui/public/locales/ru_RU.json | 6 +- src/tribler/ui/public/locales/zh_CN.json | 6 +- src/tribler/ui/src/App.tsx | 62 +++++++++++++++++++ src/tribler/ui/src/services/ipv8.service.ts | 2 + src/tribler/ui/src/services/reporting.ts | 19 ++++++ .../ui/src/services/tribler.service.ts | 4 +- 9 files changed, 111 insertions(+), 6 deletions(-) create mode 100644 src/tribler/ui/src/services/reporting.ts diff --git a/src/tribler/ui/public/locales/en_US.json b/src/tribler/ui/public/locales/en_US.json index 25b434b85e..8b844a2a24 100644 --- a/src/tribler/ui/public/locales/en_US.json +++ b/src/tribler/ui/public/locales/en_US.json @@ -130,5 +130,9 @@ "VersionAvailable": "NEW VERSION AVAILABLE", "VersionUpgrading": "Upgrading", "VersionImport": "IMPORT", - "VersionRemove": "REMOVE" + "VersionRemove": "REMOVE", + "ErrorNotification": "Tribler encountered an error! What do you want to do?", + "ErrorSearchButton": "Search for solutions", + "ErrorReportButton": "Report on GitHub", + "ErrorIgnoreButton": "Ignore" } diff --git a/src/tribler/ui/public/locales/es_ES.json b/src/tribler/ui/public/locales/es_ES.json index f412adc071..4f03ddbe3c 100644 --- a/src/tribler/ui/public/locales/es_ES.json +++ b/src/tribler/ui/public/locales/es_ES.json @@ -130,5 +130,9 @@ "VersionAvailable": "NUEVA VERSIÓN DISPONIBLE", "VersionUpgrading": "Actualización", "VersionImport": "IMPORTAR", - "VersionRemove": "ELIMINAR" + "VersionRemove": "ELIMINAR", + "ErrorNotification": "¡Tribler encontró un error! ", + "ErrorSearchButton": "Buscar soluciones", + "ErrorReportButton": "Informe en GitHub", + "ErrorIgnoreButton": "Ignorar" } diff --git a/src/tribler/ui/public/locales/pt_BR.json b/src/tribler/ui/public/locales/pt_BR.json index 63d9d62012..b532fd15de 100644 --- a/src/tribler/ui/public/locales/pt_BR.json +++ b/src/tribler/ui/public/locales/pt_BR.json @@ -122,5 +122,9 @@ "VersionAvailable": "NOVA VERSÃO DISPONÍVEL", "VersionUpgrading": "Atualizando", "VersionImport": "IMPORTAR", - "VersionRemove": "REMOVER" + "VersionRemove": "REMOVER", + "ErrorNotification": "Tribler encontrou um erro! ", + "ErrorSearchButton": "Procure soluções", + "ErrorReportButton": "Relatório no GitHub", + "ErrorIgnoreButton": "Ignorar" } diff --git a/src/tribler/ui/public/locales/ru_RU.json b/src/tribler/ui/public/locales/ru_RU.json index 8a82d12205..bb7c40db62 100644 --- a/src/tribler/ui/public/locales/ru_RU.json +++ b/src/tribler/ui/public/locales/ru_RU.json @@ -130,5 +130,9 @@ "VersionAvailable": "ДОСТУПНА НОВАЯ ВЕРСИЯ", "VersionUpgrading": "Обновление", "VersionImport": "ИМПОРТ", - "VersionRemove": "УДАЛЯТЬ" + "VersionRemove": "УДАЛЯТЬ", + "ErrorNotification": "Триблер обнаружил ошибку! ", + "ErrorSearchButton": "Поиск решений", + "ErrorReportButton": "Отчет на GitHub", + "ErrorIgnoreButton": "игнорировать" } diff --git a/src/tribler/ui/public/locales/zh_CN.json b/src/tribler/ui/public/locales/zh_CN.json index 9750d293a7..15d0fd9937 100644 --- a/src/tribler/ui/public/locales/zh_CN.json +++ b/src/tribler/ui/public/locales/zh_CN.json @@ -129,5 +129,9 @@ "VersionAvailable": "新版本上线", "VersionUpgrading": "升级中", "VersionImport": "进口", - "VersionRemove": "消除" + "VersionRemove": "消除", + "ErrorNotification": "Tribler 遇到错误!", + "ErrorSearchButton": "搜索解决方案", + "ErrorReportButton": "在 GitHub 上报告", + "ErrorIgnoreButton": "忽略" } diff --git a/src/tribler/ui/src/App.tsx b/src/tribler/ui/src/App.tsx index eecf0c8ec7..6becc1e480 100644 --- a/src/tribler/ui/src/App.tsx +++ b/src/tribler/ui/src/App.tsx @@ -2,12 +2,74 @@ import { RouterProvider } from "react-router-dom"; import { ThemeProvider } from "./contexts/ThemeContext"; import { router } from "./Router"; import { LanguageProvider } from "./contexts/LanguageContext"; +import { Button } from "@/components/ui/button"; +import { useTranslation } from "react-i18next"; import './i18n'; +function collapseError(){ + const error_popup = document.querySelector("#error_popup"); + if (error_popup && !error_popup.classList.contains("hidden")) { + // Hide if we are not hidden + error_popup.classList.toggle("hidden"); + } +} + +function reportError() { + const error_popup_text = document.querySelector("#error_popup_text"); + if (error_popup_text){ + const err_text = "Hi! I was using Tribler and THIS happened! :cry:\r\n```\r\n" + error_popup_text.textContent + "\r\n```"; + const url = encodeURI("https://github.com/Tribler/tribler/issues/new?body=" + err_text); + window.open(url, '_blank')?.focus(); + } + collapseError(); +} + +function searchError() { + const error_popup_text = document.querySelector("#error_popup_text"); + if (error_popup_text?.textContent){ + const err_lines = error_popup_text.textContent.split(/\r?\n/); + var url = ""; + + if (err_lines.length > 1){ + const err_file_raw = err_lines[err_lines.length-4]; + const last_f_name = Math.max(err_file_raw.lastIndexOf('/'), err_file_raw.lastIndexOf('\\')); + const err_file = err_file_raw.substring(last_f_name + 1).replace(/"/g,'').replace(/,/g,''); + + const err_exception = err_lines[err_lines.length-2]; + + url = encodeURI("https://github.com/Tribler/tribler/issues?q=is:issue+" + err_file + "+" + err_exception); + } else { + url = encodeURI("https://github.com/Tribler/tribler/issues?q=is:issue+" + error_popup_text.textContent); + } + window.open(url, '_blank')?.focus(); + } +} + export default function App() { + const { t } = useTranslation(); + return ( + diff --git a/src/tribler/ui/src/services/ipv8.service.ts b/src/tribler/ui/src/services/ipv8.service.ts index 4fd3a52602..447727604b 100644 --- a/src/tribler/ui/src/services/ipv8.service.ts +++ b/src/tribler/ui/src/services/ipv8.service.ts @@ -1,6 +1,7 @@ import { Circuit } from "@/models/circuit.model"; import { OverlayStats } from "@/models/overlay.model"; import axios, { AxiosInstance } from "axios"; +import { handleHTTPError } from "./reporting"; export class IPv8Service { @@ -12,6 +13,7 @@ export class IPv8Service { baseURL: this.baseURL, withCredentials: true, }); + this.http.interceptors.response.use(function (response) { return response; }, handleHTTPError); } diff --git a/src/tribler/ui/src/services/reporting.ts b/src/tribler/ui/src/services/reporting.ts new file mode 100644 index 0000000000..9f23ae3062 --- /dev/null +++ b/src/tribler/ui/src/services/reporting.ts @@ -0,0 +1,19 @@ +import axios, { AxiosError } from "axios"; + +export function handleHTTPError(error: Error | AxiosError) { + const error_popup_text = document.querySelector("#error_popup_text"); + if (!error_popup_text){ + return Promise.reject(error); + } + if (axios.isAxiosError(error) && error.response?.data?.error?.message){ + error_popup_text.textContent = error.response.data.error.message.replace(/(?:\n)/g, '\r\n'); + } else { + error_popup_text.textContent = `${error}`; + } + const error_popup = document.querySelector("#error_popup"); + if (error_popup && error_popup.classList.contains("hidden")) { + // Unhide if we were hidden + error_popup.classList.toggle("hidden"); + } + return Promise.reject(error); +} diff --git a/src/tribler/ui/src/services/tribler.service.ts b/src/tribler/ui/src/services/tribler.service.ts index aed9a2f89e..13a082a57d 100644 --- a/src/tribler/ui/src/services/tribler.service.ts +++ b/src/tribler/ui/src/services/tribler.service.ts @@ -5,6 +5,7 @@ import { Path } from "@/models/path.model"; import { GuiSettings, Settings } from "@/models/settings.model"; import { Torrent } from "@/models/torrent.model"; import axios, { AxiosInstance } from "axios"; +import { handleHTTPError } from "./reporting"; export class TriblerService { @@ -19,7 +20,8 @@ export class TriblerService { baseURL: this.baseURL, withCredentials: true, }); - this.events = new EventSource(this.baseURL + '/events', { withCredentials: true }) + this.http.interceptors.response.use(function (response) { return response; }, handleHTTPError); + this.events = new EventSource(this.baseURL + '/events', { withCredentials: true }); // Gets the GuiSettings this.getSettings(); }