fix: add environment in error report issue template
Signed-off-by: Innei <i@innei.in>
This commit is contained in:
parent
d63a9d820b
commit
232c24de3d
|
|
@ -36,6 +36,7 @@ export default defineConfig({
|
|||
"@env": resolve("./src/env.ts"),
|
||||
},
|
||||
},
|
||||
|
||||
plugins: [
|
||||
react(),
|
||||
sentryVitePlugin({
|
||||
|
|
@ -61,6 +62,7 @@ export default defineConfig({
|
|||
],
|
||||
build: {
|
||||
sourcemap: !!process.env.CI,
|
||||
target: "esnext",
|
||||
},
|
||||
define: {
|
||||
APP_VERSION: JSON.stringify(pkg.version),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { createAtomHooks } from "@renderer/lib/jotai"
|
||||
import { getStorageNS } from "@renderer/lib/ns"
|
||||
import { noop } from "foxact/noop"
|
||||
import { atomWithStorage, createJSONStorage } from "jotai/utils"
|
||||
import type { SyncStorage } from "jotai/vanilla/utils/atomWithStorage"
|
||||
|
||||
|
|
@ -104,7 +105,7 @@ export const AudioPlayer = {
|
|||
status: "playing",
|
||||
duration: this.audio.duration === Infinity ? 0 : this.audio.duration,
|
||||
})
|
||||
})
|
||||
}).catch(noop)
|
||||
},
|
||||
teardown() {
|
||||
this.currentTimeTimer && clearInterval(this.currentTimeTimer)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { attachOpenInEditor } from "@renderer/lib/dev"
|
|||
import { getNewIssueUrl } from "@renderer/lib/issues"
|
||||
import { clearLocalPersistStoreData } from "@renderer/store/utils/clear"
|
||||
import { useEffect, useRef } from "react"
|
||||
import { isRouteErrorResponse, useRouteError } from "react-router-dom"
|
||||
import { isRouteErrorResponse, useNavigate, useRouteError } from "react-router-dom"
|
||||
import { toast } from "sonner"
|
||||
|
||||
import { Button } from "../ui/button"
|
||||
|
|
@ -10,6 +10,7 @@ import { PoweredByFooter } from "./PoweredByFooter"
|
|||
|
||||
export function ErrorElement() {
|
||||
const error = useRouteError()
|
||||
const navigate = useNavigate()
|
||||
const message = isRouteErrorResponse(error) ?
|
||||
`${error.status} ${error.statusText}` :
|
||||
error instanceof Error ?
|
||||
|
|
@ -46,11 +47,7 @@ export function ErrorElement() {
|
|||
<div className="center flex flex-col">
|
||||
<i className="i-mgc-bug-cute-re size-12 text-red-400" />
|
||||
<h2 className="mb-4 mt-12 text-2xl">
|
||||
Sorry,
|
||||
{" "}
|
||||
{APP_NAME}
|
||||
{" "}
|
||||
has encountered an error
|
||||
Sorry, {APP_NAME} has encountered an error
|
||||
</h2>
|
||||
</div>
|
||||
<h3 className="text-xl">{message}</h3>
|
||||
|
|
@ -77,7 +74,11 @@ export function ErrorElement() {
|
|||
>
|
||||
Reset Local Database
|
||||
</Button>
|
||||
<Button onClick={() => (window.location.href = "/")}>
|
||||
<Button onClick={() => {
|
||||
navigate("/")
|
||||
window.location.reload()
|
||||
}}
|
||||
>
|
||||
Reload
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -103,7 +104,18 @@ export const FallbackIssue = ({
|
|||
className="ml-2 cursor-pointer text-theme-accent-500 duration-200 hover:text-accent"
|
||||
href={getNewIssueUrl({
|
||||
title: `Error: ${message}`,
|
||||
body: `### Error\n\n${message}\n\n### Stack\n\n\`\`\`\n${stack}\n\`\`\``,
|
||||
body: [
|
||||
"### Error",
|
||||
"",
|
||||
message,
|
||||
"",
|
||||
"### Stack",
|
||||
"",
|
||||
"```",
|
||||
stack,
|
||||
"```",
|
||||
|
||||
].join("\n"),
|
||||
label: "bug",
|
||||
})}
|
||||
target="_blank"
|
||||
|
|
|
|||
|
|
@ -29,13 +29,18 @@ export const SentryConfig: BrowserOptions = {
|
|||
return null
|
||||
}
|
||||
|
||||
if (error instanceof CustomSafeError) {
|
||||
return null
|
||||
}
|
||||
if (error instanceof FetchError) {
|
||||
return null
|
||||
}
|
||||
const isPassthroughError = [CustomSafeError, FetchError].some(
|
||||
(errorType) => {
|
||||
if (error instanceof errorType) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
)
|
||||
|
||||
if (isPassthroughError) {
|
||||
return null
|
||||
}
|
||||
return event
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import { repository } from "@pkg"
|
||||
|
||||
import { detectBrowser, getOS } from "./utils"
|
||||
|
||||
interface IssueOptions {
|
||||
title: string
|
||||
body: string
|
||||
|
|
@ -13,9 +15,27 @@ export const getNewIssueUrl = ({
|
|||
const baseUrl = `${repository.url}/issues/new`
|
||||
|
||||
const searchParams = new URLSearchParams()
|
||||
if (body) searchParams.set("body", (body))
|
||||
|
||||
const ua = navigator.userAgent
|
||||
const appVersion = APP_VERSION
|
||||
const env = window.electron ? "electron" : "web"
|
||||
const os = getOS()
|
||||
const browser = detectBrowser()
|
||||
|
||||
const nextBody = [
|
||||
body || "",
|
||||
"",
|
||||
"### Environment",
|
||||
"",
|
||||
`**App Version**: ${appVersion}`,
|
||||
`**OS**: ${os}`,
|
||||
`**User Agent**: ${ua}`,
|
||||
`**Env**: ${env}`,
|
||||
`**Browser**: ${browser}`,
|
||||
].join("\n")
|
||||
searchParams.set("body", nextBody)
|
||||
if (label) searchParams.set("label", label)
|
||||
if (title) searchParams.set("title", (title))
|
||||
if (title) searchParams.set("title", title)
|
||||
|
||||
return `${baseUrl}?${searchParams.toString()}`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,6 +76,28 @@ export const getOS = memoize((): OS => {
|
|||
return os as OS
|
||||
})
|
||||
|
||||
export function detectBrowser() {
|
||||
const { userAgent } = navigator
|
||||
if (userAgent.includes("Edg")) {
|
||||
return "Microsoft Edge"
|
||||
} else if (userAgent.includes("Chrome")) {
|
||||
return "Chrome"
|
||||
} else if (userAgent.includes("Firefox")) {
|
||||
return "Firefox"
|
||||
} else if (userAgent.includes("Safari")) {
|
||||
return "Safari"
|
||||
} else if (userAgent.includes("Opera")) {
|
||||
return "Opera"
|
||||
} else if (
|
||||
userAgent.includes("Trident") ||
|
||||
userAgent.includes("MSIE")
|
||||
) {
|
||||
return "Internet Explorer"
|
||||
}
|
||||
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
export const isSafari = memoize(() => {
|
||||
if (ELECTRON) return false
|
||||
const ua = window.navigator.userAgent
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import {
|
|||
import { useAuthQuery, useTitle } from "@renderer/hooks/common"
|
||||
import { stopPropagation } from "@renderer/lib/dom"
|
||||
import { FeedViewType } from "@renderer/lib/enum"
|
||||
import { getNewIssueUrl } from "@renderer/lib/issues"
|
||||
import { cn } from "@renderer/lib/utils"
|
||||
import type { ActiveEntryId } from "@renderer/models"
|
||||
import {
|
||||
|
|
@ -30,6 +31,8 @@ import {
|
|||
import { Queries } from "@renderer/queries"
|
||||
import { useEntry, useEntryReadHistory } from "@renderer/store/entry"
|
||||
import { useFeedById, useFeedHeaderTitle } from "@renderer/store/feed"
|
||||
import type { FallbackRender } from "@sentry/react"
|
||||
import { ErrorBoundary } from "@sentry/react"
|
||||
import type { FC } from "react"
|
||||
import { useEffect, useLayoutEffect, useRef } from "react"
|
||||
|
||||
|
|
@ -205,38 +208,39 @@ export const EntryContentRender: Component<{ entryId: string }> = ({
|
|||
|
||||
<WrappedElementProvider boundingDetection>
|
||||
<TitleMetaHandler entryId={entry.entries.id} />
|
||||
<ShadowDOM>
|
||||
<div className="prose mx-auto mb-32 mt-8 max-w-full cursor-auto select-text break-all text-[0.94rem] dark:prose-invert">
|
||||
{(summary.isLoading || summary.data) && (
|
||||
<div className="my-8 space-y-1 rounded-lg border px-4 py-3">
|
||||
<div className="flex items-center gap-2 font-medium text-zinc-800 dark:text-neutral-400">
|
||||
<i className="i-mgc-magic-2-cute-re align-middle" />
|
||||
<span>AI summary</span>
|
||||
</div>
|
||||
<AutoResizeHeight
|
||||
spring
|
||||
className="text-sm leading-relaxed"
|
||||
>
|
||||
{summary.isLoading ?
|
||||
SummaryLoadingSkeleton :
|
||||
summary.data}
|
||||
</AutoResizeHeight>
|
||||
<div className="mx-auto mb-32 mt-8 max-w-full cursor-auto select-text break-all text-[0.94rem]">
|
||||
{(summary.isLoading || summary.data) && (
|
||||
<div className="my-8 space-y-1 rounded-lg border px-4 py-3">
|
||||
<div className="flex items-center gap-2 font-medium text-zinc-800 dark:text-neutral-400">
|
||||
<i className="i-mgc-magic-2-cute-re align-middle" />
|
||||
<span>AI summary</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!isInReadabilityMode ? (
|
||||
<HTML
|
||||
as="article"
|
||||
className="prose-h1:text-[1.6em]"
|
||||
renderInlineStyle={readerRenderInlineStyle}
|
||||
<AutoResizeHeight
|
||||
spring
|
||||
className="text-sm leading-relaxed"
|
||||
>
|
||||
{content}
|
||||
</HTML>
|
||||
{summary.isLoading ?
|
||||
SummaryLoadingSkeleton :
|
||||
summary.data}
|
||||
</AutoResizeHeight>
|
||||
</div>
|
||||
)}
|
||||
<ErrorBoundary fallback={RenderError}>
|
||||
{!isInReadabilityMode ? (
|
||||
<ShadowDOM>
|
||||
<HTML
|
||||
as="article"
|
||||
className="prose dark:prose-invert prose-h1:text-[1.6em]"
|
||||
renderInlineStyle={readerRenderInlineStyle}
|
||||
>
|
||||
{content}
|
||||
</HTML>
|
||||
</ShadowDOM>
|
||||
) : (
|
||||
<ReadabilityContent entryId={entryId} />
|
||||
)}
|
||||
</div>
|
||||
</ShadowDOM>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</WrappedElementProvider>
|
||||
{!content && (
|
||||
<div className="center mt-16">
|
||||
|
|
@ -327,7 +331,7 @@ const ReadabilityContent = ({ entryId }: { entryId: string }) => {
|
|||
</div>
|
||||
)}
|
||||
|
||||
<HTML as="article" className="prose-h1:text-[1.6em]">
|
||||
<HTML as="article" className="prose dark:prose-invert prose-h1:text-[1.6em]">
|
||||
{result?.content ?? ""}
|
||||
</HTML>
|
||||
</div>
|
||||
|
|
@ -392,3 +396,37 @@ const ReadabilityAutoToggle = ({ url, id }: { url: string, id: string }) => {
|
|||
|
||||
return null
|
||||
}
|
||||
|
||||
const RenderError: FallbackRender = ({ error }) => {
|
||||
const nextError =
|
||||
typeof error === "string" ? new Error(error) : (error as Error)
|
||||
return (
|
||||
<div className="center mt-16 flex flex-col gap-2">
|
||||
<i className="i-mgc-close-cute-re text-3xl text-red-500" />
|
||||
<span className="font-sans text-sm">
|
||||
Render error: {nextError.message}
|
||||
</span>
|
||||
<a
|
||||
href={getNewIssueUrl({
|
||||
body: [
|
||||
"### Error",
|
||||
"",
|
||||
nextError.message,
|
||||
"",
|
||||
"### Stack",
|
||||
"",
|
||||
"```",
|
||||
nextError.stack,
|
||||
"```",
|
||||
].join("\n"),
|
||||
label: "bug",
|
||||
title: "Render error",
|
||||
})}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Report issue
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue