notifications: allow viewing stack trace of unexpected error

Previously, it was only possible to view the stack trace by clicking
the copy button and pasting it somewhere.
This commit is contained in:
David Lechner
2022-04-07 11:24:07 -05:00
parent c29ca56658
commit 56858390ca
5 changed files with 47 additions and 3 deletions
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
@import '../variables.scss';
pre.pb-notification-stack-trace {
max-width: $pt-grid-size * 50;
max-height: $pt-grid-size * 50;
overflow: auto;
}
@@ -3,9 +3,11 @@
// Provides special notification contents for unexpected errors.
import { AnchorButton, Button, ButtonGroup, Intent } from '@blueprintjs/core';
import './UnexpectedErrorNotification.scss';
import { AnchorButton, Button, ButtonGroup, Collapse, Intent } from '@blueprintjs/core';
import { useI18n } from '@shopify/react-i18n';
import React from 'react';
import React, { useState } from 'react';
import { useUniqueId } from '../utils/react';
import { I18nId } from './i18n';
type UnexpectedErrorNotificationProps = {
@@ -18,10 +20,25 @@ const UnexpectedErrorNotification: React.VoidFunctionComponent<
> = ({ messageId, err }) => {
// istanbul ignore next: babel-loader rewrites this line
const [i18n] = useI18n();
const [isExpanded, setIsExpanded] = useState(false);
const labelId = useUniqueId('pb-notification');
return (
<>
<p>{i18n.translate(messageId, { errorMessage: err.message })}</p>
<span>
<Button
aria-labelledby={labelId}
minimal={true}
small={true}
icon={isExpanded ? 'chevron-down' : 'chevron-right'}
onClick={() => setIsExpanded((v) => !v)}
/>
<span id={labelId}>{i18n.translate(I18nId.TechnicalInfo)}</span>
</span>
<Collapse isOpen={isExpanded}>
<pre className="pb-notification-stack-trace">{err.stack}</pre>
</Collapse>
<div>
<ButtonGroup minimal={true} fill={true}>
<Button
+1
View File
@@ -6,6 +6,7 @@
export enum I18nId {
AppNoUpdateFound = 'app.noUpdateFound',
CopyErrorMessage = 'copyErrorMessage',
TechnicalInfo = 'technicalInfo',
ReportBug = 'reportBug',
BleUnexpectedError = 'ble.unexpectedError',
BleGattPermission = 'ble.gattPermission',
+1
View File
@@ -1,5 +1,6 @@
{
"copyErrorMessage": "Copy Error Message",
"technicalInfo": "Expand for detailed technical information",
"reportBug": "Report Bug",
"app": {
"noUpdateFound": "{appName} is already up to date."
+16 -1
View File
@@ -1,6 +1,7 @@
// helper functions for React components
import React from 'react';
import React, { useState } from 'react';
import { createCountFunc } from './iter';
/**
* Callback that can be passed to onContextMenu event handlers to prevent
@@ -11,3 +12,17 @@ export const preventBrowserNativeContextMenu: React.MouseEventHandler = (e) =>
/** Style to disable pointer events. */
export const pointerEventsNone: React.CSSProperties = { pointerEvents: 'none' };
const nextId = createCountFunc();
/**
* React hook to get a unique identifier, e.g. for linking components via
* aria-labelledby.
*
* @param prefix A namespace prefix for the identifier.
* @returns A unique identifier in the form "prefix-N"
*/
export const useUniqueId = (prefix: string): string => {
const [uniqueId] = useState(`${prefix}-${nextId()}`);
return uniqueId;
};